Microsoft MVP성태의 닷넷 이야기
C#에서의 함수포인터 [링크 복사], [링크+제목 복사]
조회: 17024
글쓴 사람
왕초보
홈페이지
첨부 파일
 

안녕하세요? 성태님.
카메라 한대 사서 프로그래밍중인데요...ㅠㅠ~ dll에 파라미터로 정의된 함수포인터 골치아프네요.
카메라에 첨부된 샘플에는 C++로 아래와 같이 되어있는데...

__declspec(dllimport) MVSTATUS_CODES __stdcall MVStartGrab(HANDLE hCam,int (*StreamCB)(MV_IMAGE_INFO*,long nUserVal),long nUserVal);
...

int StreamCB(MV_IMAGE_INFO *pInfo,long nUserVal)
{
 ...
 return 0;
}
...
void CGCapDlg::OnBnClickedStart()
{
 ...
 MVStartGrab(m_hCam,StreamCB,(long)this);
 ...
}
흠~~ 위의 코드는 dll의 MVStartGrab함수가 카메라로부터 화상을 읽고 동기에 맞추어 읽은 화상데이터를 사용자에게 넘겨주기 위해 사용자처리루틴(int StreamCB(...))을
함수포인터로 넘겨받는 과정이죠. 일단 MVStartGrab(...)함수가 실행되면 동기에 맞춰 StreamCB가 주기적으로 호출되요.
C#에서 아래와 같이 변환했어요.^^

class Form1
{
 ...
 delegate short StreamCB(ref MV_IMAGE_INFO imageInfo, int nUserVal);
 [DllImport("MVGigE.dll")]
 public static extern MvStatus MVStartGrab(IntPtr hCam, StreamCB streamCB, int nUserVal);
 ...

 short OnStreamCB(ref MV_IMAGE_INFO info, int nUserVal)
 {
   ...
   return 0;
 }
 ...
 StreamCB sb;
 private void b_CamRun_Click(object sender, EventArgs e)
 {
   ...
   sb = OnStreamCB;
   MVStartGrab(m_hCam, sb, (int)this.Handle);
   ...
 }
}
나로선 어딘가 틀린데가 없어보이는데 OnStreamCB는 맨 첨 한번밖에 실행안되요.
한번만은 데이터랑 완전하게 받아요.
내보기엔 초기에 넘겨준 함수포인터를 잃어버리는것같은데 왜 그럴까요?
MFC에선 제대로 작동되요. 물론 MFC로 해도 되겠지만 품들여 C#에서 영상처리기반 자작했는데... 꼭 C#으로 돌리고 싶네요.
귀중한 시간 자꾸 앗아서 죄송합니다.








[최초 등록일: ]
[최종 수정일: 11/1/2014]


비밀번호

댓글 작성자
 



2014-11-03 12시32분
이게 문제인지는 모르겠지만, StreamCB 함수 포인터의 반환값이 int 인데, C# 측에서는 short로 되어 있습니다. 그리고, MV_IMAGE_INFO 구조체를 잘 구성했는지, sizeof 같은 방법을 이용해서 C++에서의 크기와 C#에서의 크기가 동일한지 확인해 보세요. 그 외에는, 딱히 문제가 없어 보입니다.
정성태
2014-11-03 03시28분
[왕초보] C++에서 정의된 구조체는

typedef struct _IMAGE_INFO
{
    uint64_t    nTimeStamp;        
    USHORT        nBlockId;        
    UCHAR        *pImageBuffer;
    ULONG        nImageSizeAcq;    
    UCHAR        nMissingPackets;
    uint64_t    nPixelType;        
    uint32_t    nSizeX;            
    uint32_t    nSizeY;
    uint32_t    nOffsetX;        
    uint32_t    nOffsetY;
} MV_IMAGE_INFO, * pMV_IMAGE_INFO ;

이구요 C#에서 구현한 구조체는

 unsafe public struct MV_IMAGE_INFO
 {
        public ulong nTimeStamp;        
        public ushort nBlockId;        
        public byte* pImageBuffer;    
        public uint nImageSizeAcq;    
        public byte nMissingPackets;
        public ulong nPixelType;        
        public uint nSizeX;            
        public uint nSizeY;
        public uint nOffsetX;        
        public uint nOffsetY;
        public MV_IMAGE_INFO (ulong Ts, ushort BI, byte* IB, uint ISA, byte MP, ulong PT, uint SX, uint SY, uint OX, uint OY)
        {
            nTimeStamp = Ts;
            nBlockId = BI;
            pImageBuffer = IB;
            nImageSizeAcq = ISA;
            nMissingPackets = MP;
            nPixelType = PT;
            nSizeX = SX;
            nSizeY = SY;
            nOffsetX = OX;
            nOffsetY = OY;
        }
  }

예요. 함수 반환값은 int로 바꿔보았고 unsafe예약어 잘못썼나 해서 위의 구조체 리용하는곳들에 다 unsafe달아줘봤어요. C++과 C#에서 위의 구조체 크기는 48로 같게 나오고... 하지만 결과는 같애요.^^
dll로 실행권이 넘어가면 디버그도 할수 없어 속상하네요. 이상한건 첨 한번 결과를 되돌린 후 dll이 전혀 작동 안하는건 아니고, Task Manager에서 보면, 메모리 사용량은 C++과 같은데, CPU이용량은 C#쪽이 엄청 크네요(70%정도로 CPU를 아예 독점해버리죠. ㅠㅠ~~).
결국 함수 포인터 한번 참조후에 실행주소가 향방을 잃은것같은데...???^^. 그렇다고 완전 크래쉬된건 아녜요. 다른 함수들 호출하면 제대로 작동되요.
C++에서 함수포인터는 본질상 그냥 포인터이고 C#에서는 delegate로 선언된 객체가 클래스네요. delegate로 C++에 함수포인터 넘기는 메카니즘 표상이 잘 안가요. 그리고,
C++에서 전역함수와 클래스 멤버함수의 포인터 참조형식이 좀 다르죠. 근데 C#에는 전역함수나 전역변수를 선언할수 없어요. 혹시 시리얼화된 클래스 멤버함수의 주소배치가 C++과 C#에서 조금 차이나는건 아닌지...
이런 의문점들은 배열이나 string타입에서도 같죠. C++의 CString은 구조체로 선언되었고 본질상 char형의 배렬로 구성되지만 C#의 string은 강력한 탐색기능을 제공하는 클래스이고, 근데 C++과의 호환에서는 System.Runtime.InteropServices만 using하고 그냥 통한다고 하네요.(실제로 해보면 LPCSTR 에로의 string변환도 잘 안되요.)^^ 후~~으-ㅁ~~...암튼 이루루한 메카니즘 표상을 정확히 갖고 머리를 정돈해서 봐야 할것같군요...
말이 길어져서 미안합니다. 살틀한 방조에 사의를 표합니다.

[guest]
2014-11-03 08시47분
[왕초보] p.s.
혹시 구조체에 포함된 byte*포인터변수때문이 아닌지...^^
제생각에는, 제 프로젝트에서 위의 구조체리용은 C#쪽에서 메모리를 할당한것이 아니라 C++로 컴파일된 dll에서 할당한 주소공간을 단지 넘겨받는것이라서 가비지수집과는 무관한걸로 예상되는데...
unsafe예약어를 없애고 byte*타입을 IntPtr타입으로 바꾸어주어도 별다른 변화가 없어요.제가 써넣은 코드상에서 포인터관리가 잘못되였는지 테스트 하느라 OnStreamCB함수에서 아무런 처리도 하지 않고 포인터를 넘겨줘도 호출은 한번밖에 안되요.
만일 참조를 포함한 구조체참조에 문제가 있다면, 위의 경우는 피할길이 없다는 절망감이 드네요...^^
[guest]
2014-11-03 11시21분
[왕초보] 문제가 또 있네요^^.
앞에서도 말씀드렸지만 함수포인터를 받는 dll함수는 그 포인터를 받아 일단 내부에 저장하고, thread를 창조하여 포인터로 지적된 함수를 주기적으로 호출해요.
근데 dll함수를 호출할 당시 넘겨준 함수(StreamCB)의 포인터값은 이후 가비지수집기에 의해 변경될 가능성이 있어요. 결국 dll함수의 입장에서 보면, 넘겨받은 포인터가 지적하는 함수에로의 한번 접근 후, 다음번 호출시 같은 포인터로 접근하면 그 주소에는 이미 그 함수가 없어지고, 따라서 포인터조작은 향방을 잃게되죠... (어쨋든 이건 가정이고 .Net에 왕초보인 저로서는 아마 그럴거라고...ㅎㅎㅎ)
메모리를 고정하는 fixed예약어가 있기는 한데 브레이크로 제한된 구역에서만 효과를 가지니 위의 경우에는 효력이 없고 ㅠㅠ~~...
많은 API함수들이 내부에 thread를 가지고 있고 고정된 주소에로의 자료반환을 진행해요. 이러한 경우를 예상해서 C#에서도 대책이 있을거라고 생각되요.
전 왕초보라서 가정에 가정만을 되풀이하는데 선배님의 고견 기대됩니다. 선배님께 자꾸 수고로움 끼치게 됩니다.
[guest]
2014-11-03 12시48분
우선 GC에 의한 포인터 변경은 신경쓰지 않아도 됩니다. PInvoke 호출 시에 delegate에 대해서는 자동으로 pinning 시키기 때문입니다. byte * 포인터는, 말씀하신 것처럼 OnStremCB 측에서 아무런 처리도 하지 않고 포인터를 넘겼는데도 그런 현상이 있는 것이라면 무관한 것 같습니다.

정히 안되면, 그냥 C++/CLI로 해보세요. 아니면, 간단한 C#/C++ 예제를 만들어서 IMAGE_INFO를 동일하게 넘겨보고 문제 발생 지점을 축소해서 재현해 보세요.

(그나저나... 사용하시는 용어가 특이하시군요. '살틀한 방조에 사의를 표...', '이루루한 메카니즘 표상' 같은 말은 무슨 뜻인지 모르겠습니다. ^^;)
정성태
2021-10-06 10시59분
[방문자] 정성태님, 살틀한 방조라는건 북한말 표현입니다....
콤퓨타력량을 키우려는 전사였나 봅니다.
[guest]
2021-10-07 10시06분
한편으로는, 북한에서 ^^; MFC를 할 것 같지는 않고... 뭔가, 젊은 세대에서 유행처럼 번진 그런 용어가 아닐까 싶습니다. 게다가 "이루루"라고 검색하니 일본 애니메이션 쪽 자료가 나열되는 것도 그렇고... ^^;;; 암튼, 묘현 표현들입니다.

그래도 .NET은 하는 듯합니다. ^^

북한 프로그래머가 작성한 닷넷 코드...
; http://www.simpleisbest.net/archive/2005/07/26/188.aspx
정성태
2021-10-07 11시07분
[dimohy] 아 저도 질문 읽어 내려가다 보니 아 이분 뭔가 좀 표현이 특이하다. (북한 사람인가? 까지는 생각을 못했고요) 그런데 와 문장 구조와 표현이 상당히 멋있다는 생각 또한 했습니다. 나한테 없는 유니크한 분의 문장을 보면 부럽기도 합니다.
[guest]
2021-10-08 10시32분
[방문자] 농처럼 썼지만 글 중간을 읽어보시면 '리용'이라고 하는 등 흔적은 이미 차고 넘칩니다.... 그리고 젊은(?) 사람들에게 이런 하드코어한 북한말이 유행한 적은 한번도 없습니다.
한편 북에서 정보전 능력을 키우는 쪽이건, 중국/동남아에서 흔히 하는 외화벌이 산업이건 프로그래밍 스킬은 상당히 크게 요구됩니다. 합법적, 불법적을 막론하고요. MFC가 필요한 일은 충분히 많을겁니다.

북한에서 인터넷으로 접속해서 타국인들에게 물어보는 일들이 전례가 없는것도 아니구요. 확정된게 없으니 그렇지...
https://kldp.org/node/108269
[guest]
2021-10-08 10시36분
[방문자] dimohy님, 이미 북한말은 우리와 많이 갈라져 있으니까요... 영어를 쓰는 나라들끼리도 어법과 단어가 다르듯이요
멋보다도 외국어스러운 거죠.
[guest]
2021-10-08 10시49분
[방문자] 이루루로 검색해서 일본 애니가 나오는건 어쩌다 그런 이름의 캐릭터가 있기 때문일겁니다 ㅋㅋㅋ 이모티콘이나 말투만 보아도 최소 30후반 이상, pc통신시대 이상의 말투인데 '젊은 세대'라면 그게 더 놀라운 일일겁니다.
메카니즘 표상representation of mechanism 같은 표현이 자연스럽게 말에 스며있다는 게 놀랍지 않으십니까 ㅎㅎ
[guest]
2021-10-08 12시00분
kldp 링크 글은 너무 티나지 않나요? 아이디부터 redstar라고 하는데... 정말 북한 사람이라면 그런 아이디를 지을까요? ^^;;; 게다가 그 아이디로 올린 지난 글들을 보면("https://kldp.org/user/58175/track") 전혀 북한 사람같지 않습니다.

그런데... 갑자기 덧글이 이상한 방향으로 흐르는군요. ^^; 이 글을 작성하신 분이 북한 사람인지, 탈북해 IT 교육 수강 중인지... 자세한 정보를 알 수 있는 단서가 없으므로 더 이상의 (글과 관련 없는) 덧글은 삭제하겠습니다.
정성태
2021-10-12 08시41분
[방문자] 앗, 알겠습니다. 저도 댓글을 더 이상 달지 않겠습니다.
생각해보면 덧글 출신지를 증명할 의무감이나 확증을 가진 것도 아니었는데... 애니메이션 키워드 검색 히트수 같은 것을 말씀하시기에 가볍게 말을 시작했다가 '이 말투가 북한식인가' 에 대해 납득기준을 확 엄격하게 가져가시는 것 같아 당황해서 공을 들이려 했나봅니다.
댓글란을 잡아먹어 실례했습니다.
[guest]

... [16]  17  18  19  20  21  22  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
55358/5/20216773안녕하세요. 초보 웹 개발자입니다. [10]파일 다운로드2
5534하영7/28/20215276clrprofiler 를 사용하여 세션정보 접근 [6]파일 다운로드1
5533함준혁7/20/20214771.net fpspread 관련 질문입니다.. [1]
5532조윤상7/15/20216124바인딩은 성공 했습니다. 그런데 브라우저에서 인증서가 없다고 나옵니다. [2]
5530ocm7/14/20215752pthread_create [7]파일 다운로드1
5529ksc7/13/20214913Source Generator 관련 질문이 있습니다. [1]
5528초심으로7/9/20216116MDI 에서 USB 연결해제 알림이 안되는 문제 질문 드려봅니다. [7]파일 다운로드1
5527wuny7/7/20214982제어관련 고민을하다가 소캣방식 선택 [2]
5526이성열 donator7/7/20216557wpf x64로 만든 메인 프로그램에서 dll로 된 UserControl 속성이 디자인타임에 잘 안보이는 문제 [10]파일 다운로드2
5525Wuny7/7/20217103제가 만든 배포파일은 window에서 막는걸까요? [2]파일 다운로드1
5524하이스컬7/2/20216414특정 이벤트에서 다른 이벤트 호출 관련 문의 [3]
5523민우7/1/202112130도커 사용시 윈도우 이미지 생성도 가능한가요? [2]
5522질문6/28/20216825WPF에서 splash screen이 나타나는 위치를 변경할 수 있나요? [3]
5521김민혁6/24/20216949.exe 파일 에러에 관한 질문 입니다. [3]
5520한예지 donator6/21/20216711랜덤함수 질문있습니다!! [2]
5519리얼킴6/19/20215651.net framwork 4.0 에서 4.8로 꼭 가야할까요?? [1]
5518한예지 donator6/18/20216415ArrayList, IList에 대해 질문 있습니다. [3]
5517wunsy6/18/20216814winform에서 Button 활성화, 비활성화 [4]
5516ocm6/15/20215813mips 어셈블리 연산 다시 질문드려요 (첨부파일 갱신됨) [2]파일 다운로드1
5515ocm6/14/20216706mips 어셈블리 연산 [6]파일 다운로드1
5514jongs6/11/20217420GethashCode와 String대한 질문 [2]
5513labe...6/11/20217175C# Winform 에서 Label에 동일한 Color를 넣었을 때 처리방법이 궁금합니다. [2]
55126/11/20217928xlwings 가 실행조차 되지 않습니다. ㅠㅠ [7]
5511Syong6/9/20216772User Control에 string array 속성 추가하는 방법 [4]
5510jay6/8/20215787string 문자열에 쌍따옴표(")를 넣고 싶습니다. [1]파일 다운로드1
5509한예지 donator6/3/20215737ExeccuteNonQuery 질문있습니다! [2]
... [16]  17  18  19  20  21  22  23  24  25  26  27  28  29  30  ...