Marshall char **来解决从托管代码中调用非托管代码的问题

时间:2011-05-20 08:13:07

标签: c++ marshalling unmanaged managed

我有这个C ++函数,

    bool MyClass::my_function(int num, TCHAR** filepath)

我将该功能公开为

    extern "C"
    {
      __declspec(dllexport) bool MyFunction(int num, char* filepath[])
      {
          OutputDebugStringA("--MyFunction--");
          TCHAR **w_filepath = (TCHAR **)calloc(num, 2* sizeof(TCHAR **));
          for(int i = 0; i < num; i++) 
          {
            OutputDebugStringA(filepath[i]);
            int len = strlen(filepath[i]) + 1;
            w_filepath[i] = (TCHAR *)calloc (1, len);
            ctow(w_filepath[i], filepath[i]); // converts char to WCHAR
          }

          bool ret = MyClass.my_function(num, w_filepath);
          OutputDebugStringA("End -- MyFunction --");
          free(w_filepath);
          return ret;
      }
    }

我将C#包装为

    [DllImport("MyDll.dll")]
    public static extern bool MyFunction(int num, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPTStr)] string[] filepath);

在C#中,我将Myfunction称为

    string [] filepath = { "D:\\samplefile\\abc.txt", "D:\\samplefile\\def.txt"}
    MyFunction(2, filepath)

在C ++函数中,它只获取filepath的第一个字符。 例如,如果我使用

在C ++代码中打印,则从上面调用
    OutputDebugStringA

它只为第一个和第二个打印D.

如果我删除

    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPTStr)]

来自c#wrapper 我将在

中收到访问冲突错误
    w_filepath[i] = (TCHAR *)calloc (1, len) 

代表第二档。

请帮帮我。

1 个答案:

答案 0 :(得分:1)

1)w_filepath[i] = (TCHAR *)calloc (1, len); - calloc需要以字节为单位的大小,因此它应该是w_filepath[i] = (wchar_t *)calloc (1, len*sizeof(wchar_t));

2)来自c#的数据来自wchar_t *,因此您根本不需要转换例程,并且应该将函数声明更改为

__declspec(dllexport) bool MyFunction(int num, wchar_t* filepath[])