我有一个跨平台的c ++代码动态库,大多数只是本机c ++。然后我从我的主exe中使用这个动态库。到目前为止,所有使用gcc的OSX都很好。现在我在Windows上我很困惑,我应该使用什么方法进入dll。我目前没有DllMain功能,因为gcc中不需要它(据我所知)。我的初步测试工作但是在检查时发现奇怪的是我的一个类构造函数被调用dll加载,所以我想我需要在windows上做更多的事情。我也是这样:
当我执行上述任一操作时,我开始收到编译器投诉,“.CRT部分存在,可能存在未处理的静态初始化器或终结器”
我已经使用article了解了这一点,但是对于最佳前进方向的任何建议和清晰度都将不胜感激。对于我需要做的事情,我的脑子里有点模糊。
答案 0 :(得分:4)
根据.CRT错误,你肯定需要一个DllMain函数。对于大多数Windows编译器,将自动为您提供DllMain,因此您无需自己编写。根据您问题的其他部分,您似乎最有可能使用的是Visual C ++,其CRT确实为您提供了DllMain。因此,虽然您确实需要DllMain,但您无需为其编写代码。
默认的VC CRT DllMain用于初始化有问题的DLL的CRT,并初始化dll提供的所有静态/全局变量。
Unix和Windows上的DLL模型有很大不同,您应该将每个DLL视为具有更“私有”的状态集。虽然,如果所有Dll都选择使用相同版本的CRT dll,那么将会共享该状态中的一些。
因为CRT正在为您提供DllMain,所以不应该在链接器上抛出/ noentry。
.CRT部分存在错误(你必须通过throw / noentry看到)告诉你需要一个DllMain,因为你的DLL中有一个或多个需要静态初始化的对象。
马丁
答案 1 :(得分:0)
如果它只是一个图书馆,那么NOENTRY就足够了。 DllMain用于控制DLL发生的事件(即附加,分离等)。
答案 2 :(得分:0)
您可以稍微更改代码以避免所有入口点,但主要是。本质上,如果您在函数外部定义了任何变量(全局但不是静态链接),请将它们包装在函数调用中。使用经常被遗忘的静态函数变量。 即,改变全球声明
SomeType var_name;
到此:
SomeType & var_name(){static SomeType var; return var;}
同样,您可以通过更改以下内容来更改静态类实例变量:
struct Container{
Container();
static Container instance;
};
Container Container::instance;
到此:
struct Container{
Container();
static Container & instance();
};
Container & Container::instance(){
static Container var;
return var;
}
这实际上是一个单例,但如果第一次访问实例将来自多线程环境,可能会出现一些并发问题。实际上,要记住的是,与全局定义的变量不同,静态本地定义的变量将在第一次调用函数时初始化。