你好Stackoverflow社区!
我正试图用一个非常老的用C ++编写的dll在C#程序中进行互操作,但是我面临着一个很大的问题:
我的C ++ DLL公开了具有以下签名的方法getPlugin:
extern "C" Plugin* getPlugin();
带有Plugin的定义:
virtual void onLoad(Service* service) = 0;
virtual const char *getDescription()const = 0;
Service类的定义:
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();
}
Plugin类的实现,其中包含与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;
}
}
Service类的实现
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
指针没有相同的地址。
有人可以解决吗?
编辑:堆栈跟踪
void Main(string args [])
.Server.Load(表)
..func(servicePointer)
... void MyClass :: onLoad(Service *服务) CPP端
...._ service-> getLongValueConf(“ FOO”,“ BAR”,(long *)&_value)访问冲突
谢谢!
奥利维尔。
答案 0 :(得分:0)
我仍然没有找到为什么我不能在C#程序和C ++ DLL之间共享内存...我可能会写一个C ++包装程序,显式地公开我的回调。
有人遇到过这个问题吗?