这个问题是有关 "如何做出一致的dll二进制文件的跨VS版本?"

  • 我们有应用程序和建Dll 与VC6和一个新的应用程序建造的 与VC9.该VC9应用程序已经使用 Dll编制VC6,大多数 这是写在C和一个在 C++。
  • C++lib是有问题的,因为 名字装修/重整的问题。
  • 编制一切与VC9是 目前不是一个选项,因为那里 似乎是一些副作用。解决这些将是非常时间 耗时。
  • 我可以修改C++图书馆,但是它必须编制VC6.
  • C++lib基本上是面向对象-包装的另一个C图书馆。该VC9应用程序使用的一些静态功能以及一些非静态的。

而静态功能可以处理的东西一样

// Header file
class DLL_API Foo
{
    int init();
}

extern "C"
{
    int DLL_API Foo_init();
}

// Implementation file
int Foo_init()
{
    return Foo::init();
}

它不是那么容易与非静态的方法。

我的理解是, 克里斯Becke的 建议使用COM-像口不会帮助我,因为该接口成员名称仍将被装饰并且因此无法从一个二元创建了一个不同的编译器。 我说的对吗?

将唯一的解决办法是编写一个C式DLL接口的使用处理程序的对象或是我失去了一些东西?在这种情况下,我想,我可能会有较少的努力有直接使用的包裹C-库。

有帮助吗?

解决方案

口成员名将 被装饰的--他们只是抵消在一个虚表.你可以设定一个接口(使用C结构,而不是一个COM"接口")在一个标题的文件,正是如此:

struct IFoo {
    int Init() = 0;
};

然后,你可以出口的一个函数从DLL,没有重整:

class CFoo : public IFoo { /* ... */ };
extern "C" IFoo * __stdcall GetFoo() { return new CFoo(); }

这将工作现,前提是你使用一个编译器,产生兼容vtable都从.Microsoft C++已经产生相同的格式虚表由于(至少,我认为)MSVC6.1DOS,那里的虚表的是一个简单的列表指针指向的职能(与thunking在多个继承情况下)。GNU C++(如果我记忆正确的)产生vtable都从与功能的指针和相对偏差。这些都不是相互兼容。

其他提示

最大的问题时要考虑使用DLL编制有不同的C++编译器比叫EXE是存分配和目的寿命。

我假设你可以让过去的名称重整(并呼吁《公约》),这不是困难的,如果你使用一个编译器相容的重整(我认为VC6是广义的兼容VS2008),或者如果使用外部"C"。

在那里你会遇到的问题是,当分配使用的东西 new (或 malloc)从DLL,然后返回这个对话人。叫的 delete (或 free)将试图免费的对象,从一个不同的堆。这将可怕的错误。

你可以做一个COM的风格 IFoo::Release 事,或 MyDllFree() 事情。这两个,因为他们叫回的问题,将使用执行正确的 delete (或 free()),所以他们会删除了正确的对象。

或者,可以确保使用 LocalAlloc (例如),以便EXE和DLL都使用相同的堆。

嗯,我觉得 克里斯Becke的建议 只是罚款。我不会用 罗杰的第一个解决方案, ,它使用一个接口只是名义上的,因为他提到,可以碰到的问题不相容的编译器处理的抽象班和虚拟的方法。罗杰点向有吸引力的COM一致的情况 他的后续行动.

  1. 痛苦的一点:你需要学习使COM口的请求,并妥善处理工具,依靠的至少工具:Com和工具:释放。如果实现接口,可以支持多个接口,或者如果方法还可以返回的接口,可能也需要成为舒适的工具:QueryInterface.

  2. 这里的关键想法。所有的节目,使用执行情况的接口(但不要实施)使用一个共同的#include"*.h"的文件定义的界面作为一个结构(C)或C/C++类(VC++)或结构(不VC++但C++)。*。h文件能够自动适应适当地取决于你是否正在编制一C语言的程序或C++的语言程序。你不必知道的那部分简单地使用的*.h文件。什么*.h文件不是定义的接口结构或类型,可以说,IFoo,其虚拟件的功能(和唯一的功能,没有直接的可视性数据的成员在这个方法)。

  3. 头文件构成,以纪念COM二标准的方式,适用于C和适用C++不管用C++编译器被使用。(Java JNI民间想这一个。) 这意味着它的工作之间单独编制模块的任何来源的所以只要一个结构完全由功能的入境指针(a虚表)映射到存储器同样通过所有的人(因此,他们必须是所有x86 32位或所有64,例如)。

  4. 在DLL实现COM界面通过一个包装类的某种,你只需要一个工厂的入口点。一样的东西

    外部"C"HRESULT MkIFooImplementation(void**述);

其返回HRESULT(你会需要了解那些过),也将返回*pv在一个位置提供用于接收IFoo口指针。(我是撇渣和有更仔细的细节,你会需要在这里。不相信我的语法)的实际作用的刻板印象,你使用这也是宣布*.h文件。

  1. 这一点是,该工厂的入口,这始终是一个未装饰外部"C"做所有的必要的包装类创造并随后提供了一个Ifoo口指向您指定的位置.这意味着所有内存的管理创建的类和所有存管理最后确定,等等, 会发生在DLL你建立包装。这是唯一的地方,你要处理这些细节。

  2. 当你得到一个确定的结果从该工厂的功能,你已经发出的一个接口指针,它已经为您保留(有一个隐含的IFoo:Com作已经执行代表的接口指你递送).

  3. 当你完成了接口,释放它呼吁IFoo:释放方法的接口。这是最后释放的实施(在种情况下你做的更多Com会副本),会撕裂下来的类及其接口的支持在工厂DLL。这是什么让你正确地依靠一致的动态stoorage分配和释放后的接口,不论是否DLL含有工厂的功能使用相同的图书馆以调用的代码。

  4. 你也许应该实施工具:QueryInterface(如方法IFoo:QueryInterface)过,即使它总是失败。如果你想要更多复杂的与使用COM二进制界面的模型正如你有更多的经验,可以了解到提供充分的QueryInterface实现。

这可能是太多的信息,但我想指出的是,很多的问题你都面临有关的异构实现Dll解决的定义COM二进制的接口,甚至如果你不需要所有它,事实上,它提供了工作方案是有价值的。以我的经验,一旦你得到挂的这个,你将永远不会忘记如何强大,这可能是用C++和C++互操作的情况。

我还没有勾勒的资源可能需要咨询的例子和你有什么学习,以便让*.h文件和实际执行工厂的功能包装的图书馆,你想分享.如果你想要深入挖掘,大声叫喊.

还有其他的事情你需要考虑,例如它的运行时期,正在使用的各种图书馆。如果没有对象是在共享这很好,但是,这似乎很不太可能在第一眼。
克里斯*贝克尔的建议是相当准确的使用 实际 COM口可以帮你得到的二进制的兼容性需要。你的里程可能各有不同)

不好玩,老兄你是为一个很大的挫折,你可能应该得到这个:

将唯一的解决办法是编写一个 C式DLL接口的使用处理程序 的对象或是我失 什么?在这种情况下,我猜我 可能会有较少的精力用 直接使用的包裹C-库。

一个真仔细的审视。好运气。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top