2012-06-01 3 views
2

C++로 DLL을 작성했습니다. 함수 중 하나가 문자 배열에 씁니다.네이티브 C++ DLL에서 C# App으로 문자열 전달

C++ 기능

EXPORT int xmain(int argc, char argv[], char argv2[]) 
{ 
    char pTypeName[4096]; 
    ... 
    //Other pTypeName ends up populated with "Portable Network Graphics" 
    //This code verifies that pTypeName is populated with what I think it is: 
    char szBuff[64]; 
    sprintf(szBuff, pTypeName, 0); 
    MessageBoxA(NULL, szBuff, szBuff, MB_OK); 
    //The caption and title are "Portable Network Graphics" 

    ... 
    //Here, I attempt to copy the value in pTypeName to parameter 3. 
    sprintf(argv2, szBuff, 0); 

    return ret; 
} 

C# 오기

//I believe I have to use CharSet.Ansi because by the C++ code uses char[], 
    [DllImport("FirstDll.dll", CharSet=CharSet.Ansi)] 
    public static extern int xmain(int argc, string argv, ref string zzz); 

I 참조로 C 번호에서 파라미터를 전달하는 시도 및 C++ DLL이있다

private void button2_Click(object sender, EventArgs e) 
{ 
    string zzz = ""; 
    int xxx = xmain(2, @"C:\hhh.bmp", ref zzz); 
    MessageBox.Show(zzz); 

    //The message box displays 
    //MessageBox.Show displays "IstuÈst¼ÓstÄstlÄstwÄstiÑstõÖstwÍst\ 
    // aÖst[ÖstÃÏst¯ÄstÐstòÄstŽÐstÅstpÅstOleMainThreadWndClass" 

} 

C# 1 함수 파라미터를 채우는 . DLL에서 값이 올바른지 확인했지만 횡설수설이 C# 응용 프로그램에 전달됩니다.

올바른 문자열 값을 C# 문자열에 쓰려면 어떻게해야합니까?

+0

시도는 C# 프로젝트에서 "안전하지 않은"공간을 만들 수 있습니다. – dotTutorials

답변

5

StringBuilder을 사용하면 기본 코드로 입력 할 수있는 문자 배열을 전달할 수 있습니다 (Fixed-Length String Buffers 참조).

함수를 선언 :

[DllImport("FirstDll.dll", CharSet=CharSet.Ansi)] 
public static extern int xmain(int argc, string argv, StringBuilder argv2); 

그것을 사용

// allocate a StringBuilder with enough space; if it is too small, 
// the native code will corrupt memory 
StringBuilder sb = new StringBuilder(4096); 
xmain(2, @"C:\hhh.bmp", sb); 
string argv2 = sb.ToString(); 
+0

이 솔루션은 내 문제를 해결했습니다. char [] ch = new char [4096]과 같은 문자 배열을 사용할 수있을 것으로 예상했지만 실패했습니다. 왜 그런가? –

+0

IIRC,'char []'은 항상 16 비트 문자의 배열 (기본형'WCHAR')로 정렬되며'CharSet '에 의해'string' /'StringBuilder'에 대해 수행 된 ANSI/유니 코드 변환에 참여하지 않습니다. 안시. 또한,'char []'를 전달한다고해서 배열의 첫 번째 요소 (C 코드가 예상하는)에 대한 포인터를 자동으로 전달하지는 않는다고 생각합니다. 그것을 강제로하기 위해서 당신은'DllImport' 시그니처에서 매개 변수를'ref char'로 지정하고 메쏘드 호출에서'ref ch [0]'으로 호출 할 수 있습니다. –

1

DLLImport 호출에 다른 정보를 제공하십시오. 내 자신의 다음 예를 살펴 보겠습니다 :

[DllImport("tcpipNexIbnk.dll", EntryPoint = "SendData", CallingConvention = CallingConvention.Cdecl)] 
    public static extern int Send([MarshalAs(UnmanagedType.LPWStr)]string message); 

공지 사항 두 가지의 CallingConvention 매개 변수 : CallingConvention = CallingConvention.Cdecl) 그대로 그

사용. 당신이 당신의 C에있는 기본 문자열 유형으로 C# 문자열 매개 변수를 캐스팅합니다

그리고 바로 C#의 문자열 유형 뒤에, 당신은 MarshalAS 명령을 사용하여 다른 관리되지 않는 유형으로 재생할 수 있습니다

, ++ 프로그램 :

public static extern int Send([MarshalAs(UnmanagedType.LPWStr)]string message); 

희망이 있습니다.

+1

CallingConvention.Cdecl 옵션을 선택할 때 내 DLL이 __declspec (dllexport)을 사용하여 함수를 내 보내야합니다. 그 맞습니까? MarshalAs 키워드를 사용하여 문제를 해결할 수는 없지만 유니 코드 준수로 이동할 때 염두에 두어야 할 것 같습니다. –