问题提出,在C++中写了一个函数比如extern "C" __declspec(dllexport) void fun1(char** cdatas){ cdatas[0] = "0/0"; cdatas[1] = "1/0"; cdatas[2] = "2/0";}在C#中调用 [DllImport("fun1.dll", EntryPoint = "fun1", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] public static extern bool void fun1([In][Out] string[] path) static void Main(string[] args) { string[] strs = new string[3]; fun1(strs); } 此时调用正确,strs中的值是0,1,2;但是如果C++中fun1函数是这样的extern "C" __declspec(dllexport) void fun1(char** cdatas){ const char* c0 = "0/0"; const char* c1 = "1/0"; const char* c2 = "2/0"; cdatas[0] = c0; cdatas[1] = c1; cdatas[2] = c2;}C#再调用就会发现strs为空的。这个问题参考了网上诸多大虾的例子,才解决,所以要写下来。C#是宽字符,在C++中宽字符是wchar_t;但是为什么直接写cdatas[0] = "0" ……能成功呢,我想可能是C#中的string调用了重载的"="吧,因为在C#中直接写 string str1 = "test1";是对的。但是这个我不能确定。
具体修改方法是,将C++的代码改成extern "C" __declspec(dllexport) void fun1(wchar_t** cdatas){ //std::locale old_loc = std::locale::global(std::locale("")); 有中文时需要 const char* c0 = "0/0"; wchar_t wc0[2] = L"/0"; mbstowcs( wc0, c0, 2);
const char* c1 = "1"; wchar_t wc1[2] = L"/0"; mbstowcs( wc1, c1, 2); const char* c2 = "2"; wchar_t wc2[2] = L"/0"; mbstowcs( wc2, c2, 2); cdatas[0] = wc0; cdatas[1] = wc1; cdatas[2] = wc2; //std::locale::global(old_loc); 有中文时需要}
这里要注意wchar_t的长度一定要=char的长度加1;否则在C#端出现乱码。在C++工程中选常规->字符集->使用 Unicode 字符集 公共语言运行支持->公共语言运行时支持(/clr).
在C#代码中修改 CharSet = CharSet.Ansi,为 CharSet = CharSet.Auto就OK了。