以下.net到本机C代码不起作用,任何想法
extern "C" {
TRADITIONALDLL_API int TestStrRef( __inout char* c) {
int rc = strlen(c);
std::cout << "the input to TestStrRef is: >>" << c << "<<" ;
c = "This is from the C code ";
return rc;
}
}
[DllImport("MyDll.dll", SetLastError = true)]
static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s);
String abc = "InOut string";
TestStrRef(ref abc);
此时Console.WriteLine(abc)应该打印“这是来自C代码”但是没有,任何关于什么错误的想法?
仅供参考 - 我有另一个不使用ref类型字符串的测试函数,它可以正常工作
答案 0 :(得分:5)
你的代码也在C方面错了。 __inout注释只告诉编译器你可以改变“c”参数指向的缓冲区。但是指针本身位于堆栈中,如果修改了“c”参数,则不会返回调用者。 您的声明可能如下:
extern "C" {
TRADITIONALDLL_API int TestStrRef( __inout char** c) {
int rc = strlen(*c);
std::cout << "the input to TestStrRef is: >>" << *c << "<<" ;
*c = "This is from the C code ";
return rc;
}
}
和C#方:
[DllImport("MyDll.dll", SetLastError = true)]
static extern int TestStrRef(ref IntPtr c);
{
String abc = "InOut string";
IntPtr ptrOrig = Marshal.StringToHGlobalAnsi(abc)
IntPtr ptr = ptrOrig; // Because IntPtr is structure, ptr contains copy of ptrOrig
int len = TestStrRef(ref ptr);
Marshal.FreeHGlobal(ptrOrig); // You need to free memory located to abc' native copy
string newAbc = Marshal.PtrToStringAnsi(ptr);
// You cannot free memory pointed by ptr, because it pointed to literal string located in dll code.
}
答案 1 :(得分:0)
这对你有用吗?基本上只需将CallingConvention = CallingConvention.Cdecl添加到DllImport语句中。您可能还想指定CharSet(例如:CharSet:= CharSet.Unicode)
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s);