zhuwt2008 2015-03-18 21:54 采纳率: 33.3%
浏览 4860
已采纳

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:\WCF\CPP\bin\test.vshost.exe”中检测到问题。

其他信息: 对 PInvoke 函数“test!test.FUNC1::Invoke”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

两种方式不都一样吗?为什么第二种方式会报错?因为第一种方式有时运行很慢,要等很久,所以我想用第二种方式在程序启动时先LoadLibrary,之后就不会出现很慢的情况,但是第二种方式总是出错,只有在参数没有字符串类型的情况下才能运行,但是确实需要传字符串参数,哪位高手能够给个指点,代码该如何修改呢?

展开全部

  • 写回答

2条回答 默认 最新

  • 万能意志 2015-03-18 23:54
    关注

    C#默认是stdcall调用约定,你可以把委托改成下面写法
    [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
    delegate int FUNC1(string xmlSta, StringBuilder fileOut);

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)
编辑
预览

报告相同问题?

悬赏问题

  • ¥15 怎么实现数组的循环累加,simulink
  • ¥15 51单片机最小开发板系统,想让寻迹小车在全检测到黑线(寻迹模块代码在第一块板子上)时蜂鸣器响(在第二块板子上)
  • ¥15 pbootcms多选调用成列表
  • ¥15 51单片机oled显示时钟
  • ¥15 小规模TSP问题的动态规划求解
  • ¥25 kubelet.service: Failed with result 'exit-code'.
  • ¥15 bitvise黑框内一键部署v2ray提示账户没有root怎么解决
  • ¥15 车型识别以及相似度匹配中细节特征提取以及图像模糊问题
  • ¥15 怎么用鸿蒙的ArkTs写出来啊
  • ¥30 websocket服务端多线程通信
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部