问题描述
- C#调用c++的dll执行带字符串参数的函数时遇到的问题
-
我在c++项目中实现函数:
extern "C" __declspec(dllexport) int FUNC1(const char* xmlSta, char* fileOut)
{
return 0;
}
然后编译成动态库a.dll,并在C#项目中引用,
用静态加载的方式,是可以运行的,代码如下(只写调用的部分):
[DllImport("a.dll", EntryPoint = "FUNC1", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int FUNC1(string xmlSta, StringBuilder fileOut);StringBuilder sbr = new StringBuilder(10); int r1 = FUNC1("abc ", sbr); //可以运行!
但是用动态加载的方式,却报错,代码如下:
public static class NativeMethod { [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")] public static extern int LoadLibrary( [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName); [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")] public static extern IntPtr GetProcAddress(int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName); [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")] public static extern bool FreeLibrary(int hModule); } /// <summary> /// 函数指针 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> delegate int FUNC1(string xmlSta, StringBuilder fileOut); class Program { static void Main(string[] args) { StringBuilder sbr = new StringBuilder(10); //1. 动态加载C++ Dll int hModule = NativeMethod.LoadLibrary(@"a.dll"); if (hModule == 0) return; //2. 读取函数指针 IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "FUNC1"); //3. 将函数指针封装成委托 FUNC1 cFUNC1 = (FUNC1)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(FUNC1)); //4. 测试 Console.WriteLine(cFUNC1("abc ", sbr)); Console.Read(); } }
报错信息是:托管调试助手“PInvokeStackImbalance”在“E:WCFCPPbintest.vshost.exe”中检测到问题。
其他信息: 对 PInvoke 函数“test!test.FUNC1::Invoke”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。
两种方式不都一样吗?为什么第二种方式会报错?因为第一种方式有时运行很慢,要等很久,所以我想用第二种方式在程序启动时先LoadLibrary,之后就不会出现很慢的情况,但是第二种方式总是出错,只有在参数没有字符串类型的情况下才能运行,但是确实需要传字符串参数,哪位高手能够给个指点,代码该如何修改呢?
解决方案
C#默认是stdcall调用约定,你可以把委托改成下面写法
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
delegate int FUNC1(string xmlSta, StringBuilder fileOut);
解决方案二:
LoadLibrary以stdcall方式调用,而你的函数是cdecl的约定,所以堆栈不对称。
时间: 2024-10-31 16:16:18