如何通过 C# 从 C++ dll 调用 struct 中的函数

Posted

技术标签:

【中文标题】如何通过 C# 从 C++ dll 调用 struct 中的函数【英文标题】:How to call a function in struct from C++ dll by C# 【发布时间】:2013-06-06 08:07:12 【问题描述】:

我的 C# 项目必须引用一个 C++ dll,

结构中的SetConfig()是我的目标,头部看起来像

extern "C"

    int HSAPI GetSDKVersion();
    IHsFutuComm* HSAPI NewFuCommObj(void* lpReserved = NULL);

    struct IHsFutuComm:public IHSKnown
    
        virtual int HSAPI SetConfig(const char* szSection,const char* szName,const char* szVal) = 0;
        ...
    

而 C# 看起来像

class Program

    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

    public delegate Int32 GetSDKVersion();
    public delegate IntPtr NewFuCommObj(IntPtr lpReserved);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct IHsFutuComm
    
        [MarshalAs(UnmanagedType.FunctionPtr)]
        public SetConfig pSetConfig;
    

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate Int32 SetConfig(string szSection, string szName, string szVal);

    static void Main(string[] args)
    
        var pDll = LoadLibrary("HsFutuSDK.dll");
        var pGetSDKVersion = GetProcAddress(pDll, "GetSDKVersion");
        var dGetSDKVersion = (GetSDKVersion)Marshal.GetDelegateForFunctionPointer(pGetSDKVersion, typeof(GetSDKVersion));
        var sdkVersion = dGetSDKVersion();
        if (sdkVersion == 0x10000019)
        
            var pNewFuCommObj = GetProcAddress(pDll, "NewFuCommObj");
            var dNewFuCommObj = Marshal.GetDelegateForFunctionPointer(pNewFuCommObj, typeof(NewFuCommObj)) as NewFuCommObj;
            var pIHsFutuComm = dNewFuCommObj(IntPtr.Zero);
            var IHsFutuComm1 = (IHsFutuComm)Marshal.PtrToStructure(pIHsFutuComm, typeof(IHsFutuComm));

            //error here
            var re = IHsFutuComm1.pSetConfig("futu", "server", "127.0.0.1:2800");
        
    

最后一行的错误是“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。”

C#如何调用SetConfig()?

【问题讨论】:

C++ 中的结构与类没有区别,它只有默认情况下是公共的成员。您无法调用 C++ 类或结构的实例方法,您无法正确获取所需的 this 指针。您必须使用 C++/CLI 语言编写包装器。 你是对的,最后我写了一个 C++ 包装器。这是一项真正过时的技术 【参考方案1】:

在这个SetConfig中是结构体的一个(纯)虚成员函数,所以调用约定应该是一个thiscall,函数指针不保存在结构体内部就像在您的 C# 代码中一样,但在它的 vtable 中。

c++ 代码中结构的声明可能更像是 C# 中的接口,而不是 C# 中的结构。

很抱歉,我无法给出完整的答案,但我希望这能为您指明正确的方向。

【讨论】:

以上是关于如何通过 C# 从 C++ dll 调用 struct 中的函数的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 调用带有 C++ 标头的 dll

当参数之一是指针数组时,如何从 C# 调用 C++ DLL

如何从 C# 调用具有 void* 回调和对象参数的 C++ Dll 中的函数

从 C# 调用 C++ 代码而不创建 dll?

如何通过C#调用OpenCV函数(自制OpenCV的c++ dll文件)

C#如何静态调用C++中的方法(静态调用dll)