我有一个带有一堆函数的DLL。到目前为止,一切顺利,这就是DLL的作用。但是,我的DLL中的一些函数需要从加载DLL的应用程序调用函数(或访问数据)。
App.exe:
std::vector<SomeClass> objectsList;
bool foo(void)
{
...
}
LoadLibrary( "something.dll" );
something.dll:
__declspec(dllexport) void someFunction(void)
{
if ( foo() )
{
objectsList[2].someAttr = 1;
}
}
据我所知,我的DLL代码不正确,因为DLL在链接时无法知道foo
或objectsList
。所以,我看到的唯一方法是:
something.dll:
typedef bool fooType(void);
fooType* pFooFunc;
__declspec(dllexport) void setFoo(fooType* fooPtr)
{
pFooFunc = fooPtr;
}
__declspec(dllexport) void someFunction(void)
{
if ( (*pFooFunc)() )
{
... _same thing for objectsList_
}
}
App.exe:
LoadLibrary( "something.dll" );
setFoo = GetProcAddress(...);
setFoo(&foo);
我是对的,还是有更优雅的方法来做这类事情?
这里有一些解决方案:DLL需要访问其应用程序的符号但是我仍然对任何关于这种设计的讨论感兴趣。
谢谢
有两种常见的解决方案:第一种是供DLL使用某种回调;二是把函数和根目录和DLL之间共享的数据放到一个单独的DLL中
一般来说,你会传递一个指针到一个带有虚函数的对象。这样你就有了面向对象的设计和回调,而不是每个导出函数调用一个函数。
一般来说,回调是一个优雅的解决方案。
但是听起来你的DLL依赖于一个特定函数的存在和行为。如果是这种情况,那么您可能需要考虑您的应用程序和库之间是否有正确的分割。您的库将被多个应用程序使用吗?如果是,那么foo()
业务将如何运作?如果没有,那么为什么它是一个DLL?
这是一个经典的回调函数设计模式。
只要你记录了你的库的消费者需要设置一个回调函数,以及这个回调函数应该做什么,这是好的
实际上回调是这样做的最好方法->显然,正如Oli提到的依赖于外部实现的DLL可能是设计有缺陷的标志。
就我个人而言,我会尝试让我的DLL依赖于没有外部函数->除了可能从回调注册在可执行…