问题提出,在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了。