Uяo*_*Koт 5 .net c# c++ pinvoke dllexport
我有一个原生的C++(我认为)应用程序,可以配置为加载某个DLL并调用一个函数.此函数返回int,接收四个参数,应至少更改其中一个并返回一个值.根据手册,这个函数应该在C++中定义为:
__declspec( dllexport ) int funcName(const char* par1, const char* par2, char* par3, char* par4);
Run Code Online (Sandbox Code Playgroud)
但是,根据需求,此功能应在C#中实现.我使用Unmanaged Exports允许我使用:
[DllExport("funcName", CallingConvention.Cdecl)]
public static unsafe int funcName(string par1, string par2, string par3, string par4) {
// sample for par3 only when using StringBuilder instead of string
// but is similar with other types
par3 = new StringBuilder(256);
par3.Append("12345");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
参数1和2工作正常(我可以使用消息框收到的值),但是我已尝试(至少)以下作为第3和第4个参数:
char* =>
=> string
=> StringBuilder
=> char[]
Run Code Online (Sandbox Code Playgroud)
所有这些都与[In], [Out], [In,Out], out, ref.
函数应更改par3和par4的值,并将整数返回给调用应用程序.应用程序读取par3的值(它实际上是一个表示为字符串的整数)并将其写入日志文件.检查日志文件后,该值不是funcName(...)中设置的值.
最常见的值是""(空),然而使用时只char[]用out或ref似乎有值回传,但它仅仅是几个奇怪的字符(不是在了funcName设置的值).
所以问题是,如何从非托管代码调用托管DLL函数时返回char*参数?
我非常怀疑那UnmanagedImports会为你做的工作.StringBuilder除非我非常错误,否则它不会存在魔法.我认为你需要像这样编码:
[DllExport("funcName", CallingConvention.Cdecl)]
public static int funcName(string par1, string par2, IntPtr par3, IntPtr par4)
{
string inputStr = Marshal.PtrToStringAnsi(par3);
string outputStr = "foo\0";
byte[] outputBytes = Encoding.Default.GetBytes(outputStr);
Marshal.Copy(outputBytes, 0, par3, outputBytes.Length);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我已删除了,unsafe因为不需要.