2009-04-29 2 views
2

I는 DLL에 다음 C 코드 서명을 가지고마샬링 C의 DLL 코드

extern __declspec(dllexport) unsigned char * 
funct_name (int *w, int *h, char **enc, int len, unsigned char *text, int *lp, int *mp, int *ep) 

C 함수 후자 세 있지만 (H, ENC, LP, MP 및 EP w를 수정할 수 null이 될 수 있으며, 그것은 아무것도하지 않습니다. 나는

[DllImport("iec16022ecc200.dll", EntryPoint = "iec16022ecc200", ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true, CallingConvention=CallingConvention.Cdecl)] 
      static extern IntPtr CallEncode(
      [In,Out,MarshalAs(UnmanagedType.LPArray)] Int32[] width, 
      [In,Out,MarshalAs(UnmanagedType.LPArray)] Int32[] height, 
      [In,Out,MarshalAs(UnmanagedType.LPStr)] ref StringBuilder encoding, 
      int barcodeLen, 
      [MarshalAs(UnmanagedType.LPStr)] StringBuilder barcode, 
      IntPtr lenp, 
      IntPtr maxp, 
      IntPtr eccp 
      ); 


public void Foo (string textToEncode,out int width, out int height) { 
      StringBuilder text = new StringBuilder(textToEncode); 
      StringBuilder encoding = new StringBuilder(new string('a', text.Length)); 

      Int32[] w = new Int32[1]; 
      Int32[] h = new Int32[1]; 


      string encodedStr = Marshal.PtrToStringAnsi(CallEncode(w, h, ref encoding, text.Length, text, (IntPtr)0, (IntPtr)0, (IntPtr)0)); 
      width = w[0]; 
      height = h[0]; 
} 

가 나는 SystemAccessViolation을 얻고 나는 내 문제가있을 때 완전히 확실하지 않다 C#으로 다음 사용하고

.

답변

3

char *를 사용하는 관리되지 않는 메서드에 StringBuilder 참조를 전달하지 마십시오. StringBuilder 내용은 유니 코드 (wchar)입니다.

대신 StringBuilder 매개 변수를 IntPtr 매개 변수로 바꾸고 Marshal.AllocHGlobal을 사용하여 적절한 크기의 버퍼를 할당하십시오.

또한 "ref"를 사용하여 관리되지 않는 코드에 StringBuilder를 전달하는 것이 .Net 마샬 러가 지원한다고 생각하지 않습니다.

1

'char ** enc'매개 변수가 수신자에 의해 수정 될 수 있다고 언급 한 경우 'SystemAccessViolation'오류가 발생할 수 있습니다. StringBuilder는 StringBuilders 용량을 초과하지 않으면 호출 수신자에 의해 참조 해제되고 수정 될 수 있습니다.

0

C++에서 Unity의 C#으로 문자열을 전달하려고했습니다. 그리고 내가 가진 모든 것은 횡설수설이었다. 마지막으로 @popcatalin 주석을 본 후 C#의 AllocHGlobal을 사용하여 문자열에 메모리를 할당하는 해결책을 발견했습니다.

이 내 C++ 함수 :

extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API TestString(char* str, int len) 
{ 
    strcpy_s(str, len, "C++ String!!! UniversalCpp"); 
    return; 
} 

이 유니티에서 C#을 스크립트의 상단에 :

#if WRCCPP 
    [DllImport("UniversalWRCCpp", CallingConvention = CallingConvention.Cdecl)] 
#else 
    [DllImport("UniversalCpp", CallingConvention=CallingConvention.Cdecl)] 
#endif 
    private static extern void TestString(IntPtr str, int len); 

private IntPtr myPtr = IntPtr.Zero; // Pointer to allocated memory 

그리고 이것은 그 함수를 호출 유니티에서 내 C# 스크립트입니다 :

int sizeInBytes = 100; 
myPtr = Marshal.AllocHGlobal(new IntPtr(sizeInBytes)); 
TestString(myPtr, sizeInBytes); 
Debug.Log("ANSI " + Marshal.PtrToStringAnsi(myPtr)); // This prints the correct format