如何在 C# 中实现C++虚拟纯类?
How do I implement a C++ virtual pure class in C#?
你好堆栈溢出社区!
我正在尝试使用用C++编写的非常旧的 dll 在 C# 程序中互操作,我面临着一个非常大的问题:
-
我的C++ DLL公开了一个具有以下签名的方法getPlugin:
extern "C" Plugin* getPlugin();
-
使用插件的定义:
virtual void onLoad(Service* service) = 0; virtual const char *getDescription()const = 0;
-
类服务的定义:
virtual void getLongValueConf(const char *section, const char*key,long *output_value ) = 0;
-
该方法的实现
getDescription
:const char* MyClass::getDescription() const { static char buffer[512]; sprintf(buffer, "FOO"); return loc_tc_buffer; }
-
调用该方法的方法
onLoad
的实现getLongValueConf
:void MyClass::onLoad(Service* service) { _service = service; _service->getLongValueConf("FOO", "BAR",(long*) &_value); }
-
所以我在我的 C# 程序中实现:
-
包含入口点的静态包装器:
public static class Wrapper { [DllImport("MyCppDll.dll", EntryPoint= "getPlugin", CallingConvention= CallingConvention.StdCall, CharSet= CharSet.Ansi, BestFitMapping= false, ThrowOnUnmappableChar= true)] public static extern IntPtr getPlugin(); }
-
插件类的实现,其中包含与 vtable 对应的结构
:public class Plugin { [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void onLoadCb(IntPtr service); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate IntPtr getDescriptionCb(); [StructLayout(LayoutKind.Sequential)] public struct PluginVtbl { public IntPtr onLoad; public IntPtr getDescription; } }
-
服务类的实现
public class Service { [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void getLongValueConf(char[] section, char[] key, ref int output_value); [StructLayout(LayoutKind.Sequential)] public struct ServiceVtbl { public IntPtr getLongValueConf; } }
-
调用方法onLoad 和 getDescription 的内部类:
public static class Loader { private static IntPtr serverPointer; private static IntPtr vtable; private static PluginVtbl handle; private static IntPtr servicePointer; public static void Load(ServiceVtbl service) { serverPointer = SSI_getServerPlugin(); vtable = Marshal.ReadIntPtr(serverPointer, 0); handle = (PluginVtbl)Marshal.PtrToStructure(vtable, typeof(PluginVtbl)); onLoadCb func = (onLoadCb)Marshal.GetDelegateForFunctionPointer(handle.onLoad, typeof(onLoadCb)); servicePointer = new IntPtr(); int size = Marshal.SizeOf(typeof(ServiceVtbl)); servicePointer = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(service, servicePointer, false); func(servicePointer); } public static string GetDescription() { serverPointer = SSI_getServerPlugin(); vtable = Marshal.ReadIntPtr(serverPointer, 0); handle = (PluginVtbl)Marshal.PtrToStructure(vtable, typeof(PluginVtbl)); getDescriptionCb func = (getDescriptionCb)Marshal.GetDelegateForFunctionPointer(handle.getDescription, typeof(getDescriptionCb)); IntPtr pointerTemp = func(); return Marshal.PtrToStringAnsi(pointerTemp); } }
-
然后,我的程序实现:
class Program { static void Main(string[] args) { Console.WriteLine(Server.GetDescription()); ServiceVtbl table = new ServiceVtbl(); getLongValueConf delgetLongValueConf = new getLongValueConf(getLongValueConf); table.getLongValueConf = Marshal.GetFunctionPointerForDelegate(delgetLongValueConf); Server.Load(table); } static void getLongValueConf(char[] section, char[] key, ref int output_value) { Console.WriteLine("{0} {1}", section, key); } }
-
当我调用Console.WriteLine(Server.GetDescription());
时,我的输出是"FOO"。 但是当我调用Server.onLoad
方法时,我有一个 AccesViolationException。因此,我决定检查不同指针的地址,并注意到 C# 代码中的servicePointer
与C++代码中的service
指针的地址不同。
有人有解决方案吗?
编辑:堆栈跟踪
无效主(字符串参数[](。
Server.Load(table(.
.func(servicePointer(
...void MyClass::onLoad(Service* service(CPP Side
...._service->getLongValueConf("FOO", "BAR",(long*( &_value(Access Violation
谢谢!
奥利维尔。
我仍然没有找到为什么我不能在我的 C# 程序和我的 C++ DLL 之间共享内存......我可能会编写一个 C++ 包装器来显式公开我的回调。
有人遇到过这个问题吗?
- 虚拟决赛作为安全
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 如何在C++中获得"静态纯虚拟"功能?
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 大小虚拟继承中的派生类
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 使用 C++ 和 i2c 工具从虚拟 i2c 写入和读取
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如果整个应用程序是虚拟映射的,为什么 new 会进行系统调用?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- std::is_trivially_copyable_v 关于虚拟功能
- 删除C++继承中虚拟类成员的代码重复
- 子类地址等于虚拟基类地址?
- 当覆盖存在时调用基本虚拟"binded to object"函数
- 用于创建/注册虚拟存储设备的 IOKit 驱动程序
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?