- 主题:程序能只引用另一项目DLL编译吗?
目前的项目是编译为dll,在目标程序中运行。
但是项目越来越庞大,对于架构有新的认识,而且后续开发可能会涉及与多人合作,为了避免核心功能的频繁或者不小心改动,准备把基础功能抽出来做成一个类似平台的DLL(暂称为a)。然后项目引用此DLL a编译成DLL b。目标程序运行DLL b。
那么问题是:如何拆分原项目,让DLL b在编译的时候只需要DLL a这个文件即可?找到的资料大多都是说要同时提供DLL a和DLL a项目的头文件?有没有做过的给个详细点的步骤?谢谢。
#发自zSMTH@一代鸡皇水果iPhone 250 MAX
--
FROM 82.19.154.*
没看懂这是啥意思
不管怎么拆分,b都只会依赖于a的啊。难道你还要拆一个c出来?
b既然依赖于a,那么编译b时,肯定需要a的头文件。
而b又要导出接口给exe用,那么编译b时,肯定也需要b自己导出的那些接口的头文件。
所以,你想表达什么?
--
FROM 125.35.124.*
a是基础库非界面的话,依赖a的头文件和.lib。 这不妨碍你的目标:基础功能不频繁改动。假装这是别的部门/公司提供的模块。运行时才需要dll。
a是含界面的核心功能的话(框架),典型的插件机制,a对b一无所知。
a启动时,读入配置文件如json中的*.dll,然后依次LoadLibrary,p=findSymbol,调用p。p的存在是一种人的约定,没有编译器的约束。这种情况,b未依赖a,不符合你的描述。
数据层、领域层(业务层biz layer)、应用层、表现层,先分析下
架构吧。你这不叫对架构有了新的认识,是对(架构)需求有了新的认识。
想想游戏的插件机制、马丁的《整洁架构》、还有《Windows技术内幕》里关于动态加载、链接、重定位那几章。
【 在 one4all4one 的大作中提到: 】
: 目前的项目是编译为dll,在目标程序中运行。
: 但是项目越来越庞大,对于架构有新的认识,而且后续开发可能会涉及与多人合作,为了避免核心功能的频繁或者不小心改动,准备把基础功能抽出来做成一个类似平台的DLL(暂称为a)。然后项目引用此DLL a编译成DLL b。目标程序运行DLL b。
: 那么问题是:如何拆分原项目,让DLL b在编译的时候只需要DLL a这个文件即可?找到的资料大多都是说要同时提供DLL a和DLL a项目的头文件?有没有做过的给个详细点的步骤?谢谢。
: ...................
--
修改:DoorWay FROM 1.85.200.*
FROM 1.85.200.*
谢谢回复。
a准备做成基础功能性DLL,让b来使用。
b其实是最终的DLL,提供给用户exe使用。
现在的项目等于是a+b=dll
我想分成2个DLL,但是没弄过2个DLL互相调用的情况。一个的时候直接在vs里面选择目标是DLL就行了。2个的时候,直接让第二个b的项目引用a的头文件,但是a怎么加载给b,让b调用呢?
【 在 z16166 @ [CPlusPlus] 的大作中提到: 】
:
: 没看懂这是啥意思
:
: 不管怎么拆分,b都只会依赖于a的啊。难道你还要拆一个c出来?
:
#发自zSMTH@一代鸡皇水果iPhone 250 MAX
--
FROM 82.19.154.*
非常感谢,我把那个书找来看看。
我准备分出来的a是基础库,用来提供通用功能。但是如果依赖lib,那不是把a做成了静态库?这样b引用头文件和lib后,直接就编译成结果DLL了,运行时不应该需要a了吧?
因为我目前的项目,就是引用了第三方lib,但是编译后的DLL运行时并不需要其他dll。
如果我的a做成静态库得到lib,那么b依赖a就如同我目前依赖第三方lib一样,编译好b运行时应该不需要a的dll了。
不知道理解的对不对,请多多指教。
【 在 DoorWay @ [CPlusPlus] 的大作中提到: 】
:
: a是基础库非界面的话,依赖a的头文件和.lib。 这不妨碍你的目标:基础功能不频繁改动。假装这是别的部门/公司提供的模块。运行时才需要dll。
:
: a是含界面的核心功能的话(框架),典型的插件机制,a对b一无所知。
: a启动时,读入配置文件如json中的*.dll,然后依次LoadLibrary,p=findSymbol,调用p。p的存在是一种人的约定,没有编译器的约束。这种情况,b未依赖a,不符合你的描述。
#发自zSMTH@一代鸡皇水果iPhone 250 MAX
--
FROM 82.19.154.*
还有网上很多说法跟你的一样,要loadlibrary后findsymbol。那我要是有几百个函数,那不是每个都写findsymbol?这样写b的代码好累,不断的找a的函数。
那还不如把a做成静态库,让b引用a的头文件后直接编译成目标DLL算了。这样起码写代码的时候,a的导出函数都对b可见
【 在 DoorWay @ [CPlusPlus] 的大作中提到: 】
:
: a是基础库非界面的话,依赖a的头文件和.lib。 这不妨碍你的目标:基础功能不频繁改动。假装这是别的部门/公司提供的模块。运行时才需要dll。
:
: a是含界面的核心功能的话(框架),典型的插件机制,a对b一无所知。
: a启动时,读入配置文件如json中的*.dll,然后依次LoadLibrary,p=findSymbol,调用p。p的存在是一种人的约定,没有编译器的约束。这种情况,b未依赖a,不符合你的描述。
#发自zSMTH@一代鸡皇水果iPhone 250 MAX
--
FROM 82.19.154.*
此.lib是与dll配套的,里面只有简单的对于dll的描述,用于链接时让连接器扫描符号。
b运行时,体内含依赖的dll信息,如a.dll。操作系统会帮你加载起来,并重定位。
常见的错误:系统中无法找到xx.dll,即是此过程。
观察你现有的程序输出目录,可以验证1。
【 在 one4all4one 的大作中提到: 】
: 非常感谢,我把那个书找来看看。
: 我准备分出来的a是基础库,用来提供通用功能。但是如果依赖lib,那不是把a做成了静态库?这样b引用头文件和lib后,直接就编译成结果DLL了,运行时不应该需要a了吧?
: 因为我目前的项目,就是引用了第三方lib,但是编译后的DLL运行时并不需要其他dll。
: ...................
--
FROM 1.85.200.*
先去读Windows技术内幕里那几章吧,完了豁然开朗。
你这是概念性问题,自己提了假问题。
【 在 one4all4one 的大作中提到: 】
: 还有网上很多说法跟你的一样,要loadlibrary后findsymbol。那我要是有几百个函数,那不是每个都写findsymbol?这样写b的代码好累,不断的找a的函数。
: 那还不如把a做成静态库,让b引用a的头文件后直接编译成目标DLL算了。这样起码写代码的时候,a的导出函数都对b可见
:
: ...................
--
FROM 1.85.200.*
19章 Dll Basics 第三节 The overall picture
一共几页,很快就读完了。我当时读的时候欢喜的很。这书真是好书,作者真是专家。可惜的是绪言里作者预判native开发气数已尽,去搞托管语言了,令我唏嘘不已。我学习练习的东西可能拾人牙慧都算不上,难以望其项背的感觉。
【 在 one4all4one 的大作中提到: 】
: 还有网上很多说法跟你的一样,要loadlibrary后findsymbol。那我要是有几百个函数,那不是每个都写findsymbol?这样写b的代码好累,不断的找a的函数。
: 那还不如把a做成静态库,让b引用a的头文件后直接编译成目标DLL算了。这样起码写代码的时候,a的导出函数都对b可见
:
: ...................
--
FROM 1.85.200.*
VC生成的有两种lib,
一种是静态lib(包含全部代码和链接信息);
一种只是用来导入dll函数的lib(包含链接信息,无代码)。
exe/dll调用另外一个dll里的函数,也有两种方式,
一种是通过导入表(通过上面的第二种lib),隐式;
另外一种是自己LoadLibrary + GetProcAddress,显式。
函数太多,调用代码又不能做成自动生成的话,那就通过导入表好了。
DLL导出接口,尽量用纯C方式,也可以用伪COM接口(纯虚接口),避免导出普通的c++类。
windows DLL有几个大坑:
1、dllmain(或者说DLL_PROCESS_ATTACH/DLL_PROCESS_DETACH阶段)中尽量少干事情,因为此时持有loader锁,是很容易交叉加锁导致死锁的。
2、DLL中创建的线程,在创建线程之前先把dll的引用计数加1,保证线程运行时dll不会被unload,不然直接崩的;退出线程时要用专用API FreeLibraryAndExitThead,为啥用专用API可以搜一下。如果在dllmain( )中wait线程退出,也就是执行join操作,那就是找死。
3、dll中分配的内存,要由dll自己来释放,因为内存默认是从dll的私有CRT堆中分配的,别的dll/exe是没有这个堆的句柄的。所以dll中需要导出内存释放的接口,比如通过伪COM接口的Release()方法释放内存。
【 在 one4all4one 的大作中提到: 】
: 非常感谢,我把那个书找来看看。
: 我准备分出来的a是基础库,用来提供通用功能。但是如果依赖lib,那不是把a做成了静态库?这样b引用头文件和lib后,直接就编译成结果DLL了,运行时不应该需要a了吧?
: 因为我目前的项目,就是引用了第三方lib,但是编译后的DLL运行时并不需要其他dll。
: ...................
--
FROM 125.35.124.*