在未导出成员函数时,从C#调用C本机非托管成员函数

在未导出成员函数时,从C#调用C本机非托管成员函数,第1张

概述我有一个非托管DLL,只导出一个C风格的工厂方法,它返回一个类的新实例(这里简化为简单). hello.h #if defined(HWLIBRARY_EXPORT) // inside DLL# define HWAPI __declspec(dllexport)#else // outside DLL# define HWAPI __declspec(dllimport) 我有一个非托管DLL,只导出一个C风格的工厂方法,它返回一个类的新实例(这里简化为简单).

hello.h

#if defined(HWliBRARY_EXPORT) // insIDe DLL#   define HWAPI   __declspec(dllexport)#else // outsIDe DLL#   define HWAPI   __declspec(dllimport)#endifstruct HelloWorld{   public:    virtual voID sayHello() = 0;    virtual voID release() = 0;};extern "C" HWAPI HelloWorld* GetHW();

HELLO.CPP

#include "hello.h"struct HelloWorldImpl : HelloWorld{    voID sayHello(){    int triv;    std::cout<<"Hello World!";    std::cin>>triv;};voID release(){    this->HelloWorldImpl::~HelloWorldImpl();};HelloWorld* GetHW(){HelloWorld* ptr = new HelloWorldImpl();return ptr;};

现在,我可以使用dllimport访问GetHW(),但有没有办法访问返回的’struct’的成员函数…即,sayHello和release?

我也遇到了同样的问题.这个问题之前被问过一段时间.我评论它有任何更好的解决方案,但还没有得到任何答复.所以,重新发布它.

当我用Google搜索时,能够找到两种解决方案.

解决方案1:为现有的dll公开C风格的所有成员函数.我不能这样做,因为它是第三方dll.

解决方案2:编写一个托管C dll,公开本机C dll的功能,以后可以在您的C#dll中使用.这里有许多类/函数.因此,创建将花费大部分时间.

我从以下链接获得了上述解决方案.
How To Marshall

除上述两种解决方案外,请告诉我是否有更好的解决方案?

我有C解决方案的源代码.但我不是要触摸C dll.如果有可能在C#中做到这一点,那就太好了.

如果没有其他选择,我需要遵循指定的两个解决方案中的任何一个.

解决方法 C代码使用Visual C编译器实现抽象类的方式. http://blogs.msdn.com/b/oldnewthing/archive/2004/02/05/68017.aspx.此内存布局是“固定的”,因为它用于实现COM接口.内存中结构的第一个成员将是一个指向包含方法的函数指针的vtable的指针.所以对于

struct HelloWorldImpl : public HelloWorld{   public:    int value1;    int value2;}

内存中的“真实”布局是:

struct HelloWorldImpl{    HelloWorldVtbl *vtbl;    int value1;    int value2;}

其中vtbl将是:

struct HelloWorldVtbl{    voID *sayHello;    voID *release;}

只是为了做一个完整的回复,我正在写这个签名的例子:

struct HelloWorld {   public:    virtual int sayHello(int v1,int v2,int v3) = 0;    virtual voID release() = 0;};

C#代码:

[Dllimport("Nativelibrary.dll",CallingConvention = CallingConvention.Cdecl)]public static extern IntPtr GetHW();[StructLayout(LayoutKind.Sequential)]struct HelloWorldVtbl{    public IntPtr sayHello;    public IntPtr release;}

你的函数是voID Func(voID)或int Func(int,int,int),但实际上它们有一个隐藏参数,所以你可以把它们写成:

int sayHello(HelloWorld*,int);voID release(HelloWorld*);

所以在C#代表是

[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate int Int32MethodInt32Int32Int32(IntPtr ptr,int v1,int v3);[UnmanagedFunctionPointer(CallingConvention.ThisCall)]public delegate voID VoIDMethodVoID(IntPtr ptr);

然后你可以使用

IntPtr ptr = GetHW();IntPtr vtbl = Marshal.ReadIntPtr(ptr,0);HelloWorldVtblhw = (HelloWorldVtbl)Marshal.PtrToStructure(vtbl,typeof(HelloWorldVtbl));Int32MethodInt32Int32Int32 sayHello = (Int32MethodInt32Int32Int32)Marshal.GetDelegateForFunctionPointer(hw.sayHello,typeof(Int32MethodInt32Int32Int32));int res = sayHello(ptr,1,2,3);Console.Writeline(res);VoIDMethodVoID release = (VoIDMethodVoID)Marshal.GetDelegateForFunctionPointer(hw.release,typeof(VoIDMethodVoID));release(ptr);
总结

以上是内存溢出为你收集整理的在未导出成员函数时,从C#调用C本机/非托管成员函数全部内容,希望文章能够帮你解决在未导出成员函数时,从C#调用C本机/非托管成员函数所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1227292.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存