C++ DLL 으로부터 이중포인터 함수를 C#에서 구현할 때 시그니쳐 오류가 발생합니다.

오래전에 볼랜드 Cbuilder5로 만들어진 DLL 파일이 있습니다.
DLL 파일은 PC의 PCI 버스에 장착되는 커스텀 이미지 보드의 드라이버 파일입니다.

PCI 버스로 구동되는 이미지 보드의 DLL 파일이 있습니다.
OpenPCI() 함수로 버퍼 메모리 주소를 받아 이미지 데이터를 읽으면 되는데요.

전에 만들어진 C++ 코드를 보면 아래와 같이 되어 있습니다.
(Window7 32bit OS에서 C++ builder 5.0으로 작성됨)

OpenPCI(DWORD **RAMPCI) 로 DLL에 선언되어 있고

DWORD *RAMPCI;
OpenPCI(&RAMPCI);
iProm = RAMPCI[idx]; // idx : 0 ~ 0x3ffff

c#에서 다음과 같이 코드를 작성했습니다.

IntPtr pVRAM = Marshal.AllocHGlobal(4);
[DllImport(“xx.dll”, CallingConvention = CallingConvention.cdecl)]
public static extern bool OpenPCI(ref IntPtr pVRAM);
OpenPCI(ref pVRAM);

Marshal.Copy(pVRAM, linebuff, 0, length);

현재 문제는 pVRAM에 주소 같이 보이는 값은 반환되는데 버퍼를 읽다 보면
Marshal.Copy에서 보호된 메모리를 액세스 할 수 없습니다.
라는 에러가 나며 해당 주소의 메모리를 보면 ?? 처럼 보이지 않습니다.
또한, OpenPCI() 함수 실행 시 호출 및 호출되는 쪽의 시그니쳐가 맞지 않아 스택이 불안정 해진다라는 경고가 뜹니다.
C# PC는 Windows10 32bit 버젼입니다.
빌드 옵션을 x86으로 해도 오류가 해결되지 않는데 원인을 알고 싶습니다.

1개의 좋아요

성태님 블로그 질문에는 델파이 관련 내용을 누락 하셨네요.
성태님 답변은 C/C++일 경우에는 완벽한 답변입니다.

어쨋든 delphi dll p/invoke, delphi dll p/invoke memory error 요렇게 두 가지로 검색을 해 보니

이런게 나오네요.

결국 원인이 델파이 인 것으로 보이며,
해결 방법은 Microsoft C/C++에서 동작이 된다면 Microsoft C/C++로 랩핑 한 DLL을 만드시는게 좋을 것 같습니다.
C++ Builder 말고요. C++ Builder로 감싸도 될것 같긴 한데… 안써봐서 모르겠네요.

2개의 좋아요

질문자는 C++ Builder를 이야기했는데, 갑자기 델파이가 나온 이유가 뭔가요? ^^

게다가 공유해 주신 링크는, delphi의 기본 calling convention이 register 방식이기 때문에 C/C++에서 호출할 수 없다는 것이지만, 글에서도 다시 답변자가 정정한 대로 그 글의 질문자는 stdcall 방식으로 정의한 API이기 때문에 C/C++에서도 호출할 수 있는 것이 맞습니다.

마찬가지로, 이번 글의 질문자도 (제 블로그 질문에서) C/C++로는 cdecl 방식으로 호출해 정상적으로 사용했다고 하는 걸로 봐서 (대상이 Delphi냐 C++ Builder냐에 상관없이) calling convention 문제는 아닌 듯합니다. (참고로, C/C++의 경우 기본 호출 방식이 cdecl이고, Borland C++ Builder도 cdecl입니다.)

3개의 좋아요

제가 왜 그리 봤을까요?
저도 이해가 안되네요. 델파이라고 계속 생각을 하고 있었는데요.

2개의 좋아요

제가 착각을 해서 잘못된 답변을 드렸습니다. 글 쓰신분께 사과 드립니다…

2개의 좋아요

답변 감사합니다.
C++ 코드는 동작하는 줄 알았는데 다시 확인해 보니 C#과 같이 Open시 주소 반환은 되는데
버퍼 후반부에서는 protected memoty 에러가 나면서 읽지를 못합니다.
원작이 Cbuilder로 작성된 프로그램인데 이 프로그램은 잘 작동합니다.
결국 차이점은 OS가 Windows 10으로 바뀌고 개발툴이 Visual Studio로 바뀐 것인데
이 차이에 원인이 숨어 있을 것 같은데 찾기 어렵네요.

1개의 좋아요