Visual c++ 如果新的';在动态链接库中创建并导出

Visual c++ 如果新的';在动态链接库中创建并导出,visual-c++,dll,undefined,exe,Visual C++,Dll,Undefined,Exe,我正在常规DLL中新建一个堆对象。我使用uu declspec(dllexport)正确导出它,并使用u declspec(dllimport)链接将其导入EXE。只要我在DLL中,对象的定义就正确,但在EXE中执行/调试时,对象是未定义的。我错过了什么?名字弄乱了?外部“C”需要帮助吗 进一步解释: @Colin Robertson我的问题源于使用扩展DLL的原型,其代码在编译时与EXE集成。我知道我的应用程序需要从EXE直接访问DLL中的对象,这在windows扩展DLL中是可以的,因为代码

我正在常规DLL中新建一个堆对象。我使用uu declspec(dllexport)正确导出它,并使用u declspec(dllimport)链接将其导入EXE。只要我在DLL中,对象的定义就正确,但在EXE中执行/调试时,对象是未定义的。我错过了什么?名字弄乱了?外部“C”需要帮助吗

进一步解释: @Colin Robertson我的问题源于使用扩展DLL的原型,其代码在编译时与EXE集成。我知道我的应用程序需要从EXE直接访问DLL中的对象,这在windows扩展DLL中是可以的,因为代码集成。但是,由于我的应用程序在执行过程中创建了许多DLL,所以原型变成了一个内存占用器,我可能会动态地将每个DLL集成到正在运行的可执行文件中。因此,生产代码必须使用具有自动引用计数(dllmain等)的常规DLL,只要它不是静态链接的。这就引出了我当前的问题:如何从EXE中访问DLL对象

因此,链接中关于分配器传递的讨论是不相关的。Sutter和Alexandrescu书中的第60点(60.避免在不同的模块中分配和释放内存)不适用,因为EXE不负责对象生命周期。另外,由于我使用的是共享库,下面的说法是正确的:“具体来说,如果您使用Dll运行时选项,那么一个Dll-msvcrtxx.Dll-管理一个单独的freestore,该freestore在链接到该Dll的所有Dll和exe之间共享。”(请参阅StackOverflow的“谁将堆分配给我的Dll?”他的线被poke、Linus Kleen、mauris、Cody Gray、miku出于某种原因合上了)。我的代码不会将DLL的分配/解除分配职责与EXE的使用请求混为一谈

我认为问题在于,在一个常规DLL中,使用一个指针指向另一个模块的分配堆中的一个对象,该对象在另一个线程中运行,具有自己的消息泵,这是灾难性的,并且受到编译器的谴责。这是应该的

但我的问题仍然是合理的

我认为windows有两种方法可以解决这种情况。一个是Send/PostMessage调用,它在其他线程队列上发布消息,另一个是COM编组。对于前者,我会对返回值有问题。因为我所做的基本上是一个远程过程调用,所以我的EXE希望从DLL返回结果,而SendMessage只返回一个HRESULT。对于后者,这正是COM在单元线程应用程序中封送指针时所做的事情(请参阅MSDN中的“单线程单元”)。COM的设计目的是让您在线程之间甚至进程之间传递指针。可能有第三个C++的方式来使用piml习惯用法(参见),但是这种方法是更多的工作,并且有缺点。感谢MVP斯科特·麦克菲利普斯的建议


是否有人对如何进行有建议或经验?

不要这样做。这是Sutter和Alexandrescu书中的第60项,我强烈推荐。单独的模块可以使用自己版本的运行时库,包括基本的分配例程。在一个模块的堆上分配的东西可能无法从另一个模块访问,或者在分配和释放它们时有不同的约定。名称混乱的惯例可能不同,但这是你最不担心的。下面是另一个StackOverflow问题,它更详细地回答了为什么这是一个坏主意,以及如何取而代之:

您“新建”了对象,但导出了一个符号。“未定义”表示您有链接错误。外部“C”应该有帮助。在我尝试编辑答案之前,请告诉我您是使用静态导入库链接DLL,还是调用
LoadLibraryEx
。我也很好奇为什么您选择让DLL管理对象生存期,而不是让客户机构造DLL中定义的对象。消息传递用于单独的进程,而不是(通常)与DLL通信。COM更适合于通用接口和独立的生存期管理,正如您希望插件接口一样。在我提出澄清问题时,您能否通过在构造函数和析构函数中设置断点来告诉我调试器对对象生存期的说明?主要是我很好奇它是否在客户端看到它之前就被销毁了。“使用静态导入库在DLL中链接,或者如果你调用LoadLibraryEx“我在使用静态导入库。”使用静态导入库在DLL中链接,或者如果你调用LoadLibraryEx“我在编译时使用静态导入库”。在运行时,我使用AfxLoadLibrary。如果所有内容都是使用同一个CRT作为单个解决方案构建的,那么在这种情况下,一旦在运行时加载,DLL实际上就是内存中.EXE映像的一部分。堆未填充。这与链接到静态库几乎相同。如果调试器在启动时加载所有符号,则可以在任何地方中断并检查任何内容。在启动时,只有一次通过DLLMain,在应用程序被拆除时,会有另一次通过DLLMain。只有当代码由于其他原因(例如,它不是构建的)不存在时,您才会看到未定义的符号。