for*_*idt 6 c++ windows visual-c++-6 visual-c++-2008 name-decoration
这个问题与"如何跨VS版本制作一致的dll二进制文件"有关.
虽然静态函数可以用类似的东西来处理
// Header file
class DLL_API Foo
{
int init();
}
extern "C"
{
int DLL_API Foo_init();
}
// Implementation file
int Foo_init()
{
return Foo::init();
}
Run Code Online (Sandbox Code Playgroud)
使用非静态方法并不容易.
据我了解,Chris Becke建议使用类似COM的接口对我没有帮助,因为接口成员名称仍然会被装饰,因此无法从使用不同编译器创建的二进制文件中访问.我在那儿吗?
唯一的解决方案是使用处理程序写一个C风格的DLL接口到对象还是我错过了什么?在这种情况下,我想,我可能会更少的努力直接使用包装的C库.
使用使用与调用EXE不同的C++编译器编译的DLL时要考虑的最大问题是内存分配和对象生存期.
我假设您可以通过名称修改(和调用约定),如果您使用兼容的修改编译器(我认为VC6与VS2008大致兼容),或者如果您使用extern"C",这并不困难.
你遇到问题的地方是你从DLL中使用new(或malloc)分配一些东西,然后你将它返回给调用者.调用者delete(或free)将尝试从不同的堆中释放对象.这将是非常错误的.
你可以做一个COM风格的IFoo::Release东西,或者一MyDllFree()件事.这两个,因为他们回调到DLL,将使用正确的delete(或free())实现,因此他们将删除正确的对象.
或者,您可以确保使用LocalAlloc(例如),以便EXE和DLL使用相同的堆.
接口成员名称不会被修饰——它们只是 vtable 中的偏移量。您可以在头文件中定义接口(使用 C 结构,而不是 COM“接口”),因此:
struct IFoo {
int Init() = 0;
};
Run Code Online (Sandbox Code Playgroud)
然后,您可以从 DLL 导出函数,而无需修改:
class CFoo : public IFoo { /* ... */ };
extern "C" IFoo * __stdcall GetFoo() { return new CFoo(); }
Run Code Online (Sandbox Code Playgroud)
如果您使用的是生成兼容 vtable 的编译器,那么这将工作得很好。从(至少我认为)MSVC6.1 开始,Microsoft C++ 已经为 DOS 生成了相同格式的 vtable,其中 vtable 是指向函数的简单指针列表(在多重继承情况下使用 thunking)。GNU C++(如果我没记错的话)生成带有函数指针和相对偏移量的虚函数表。这些彼此不兼容。