在未导出成员函数时,从C#调用C本机/非托管成员函数
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了在未导出成员函数时,从C#调用C本机/非托管成员函数,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3106字,纯文字阅读大概需要5分钟。
内容图文
我有一个非托管DLL,只导出一个C风格的工厂方法,它返回一个类的新实例(这里简化为简单).
hello.h
#if defined(HWLIBRARY_EXPORT) // inside DLL
# define HWAPI __declspec(dllexport)
#else // outside DLL
# define HWAPI __declspec(dllimport)
#endif
struct 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, int, int);
void release(HelloWorld*);
所以在C#代表是
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
public delegate int Int32MethodInt32Int32Int32(IntPtr ptr, int v1, int v2, 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本机/非托管成员函数所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。