易语言支持库制作学习笔记

本文讲讲用VS2008制作易语言支持库(动态库和静态库)的具体方法和步骤。
这是我学习制作支持库时的学习笔记,贴出来分享下,也方便我以后查询。
时间仓促水平有限,不到之处还请各位高手们批评指正,以便完善。
本文欢迎转载,但请注明作者和出处。谢谢!
易语言支持库制作顺序是先制作动态库(dll) 再制作静态库(lib)。


I. 动态库的制作

1. 打开VS2008, 新建项目MFC DLL, 名称mylib, 完成

2. 项目属性,配置里选择所有配置 (设置debug和release模式的配置项)
项目属性 -> 常规 -> 字符集 设置为多字节字符集
项目属性 -> C++选项卡 -> 附加包含目录 填入sdk的Elib目录,如我的Elib目录是 D:\E51\sdk\cpp\ELib

3. 编写代码
1. 打开mylib.cpp文件
2. 文件头处加入
复制代码
  1. #include <lib2.h>
  2. #include <lang.h>
  3. #include <fnshare.h>
  4. #include <fnshare.cpp>

3.文件结尾处加入自己的代码

1) 定义LIB_INFO
这段代码是定义模块信息的,只在动态模块中使用,所以加入宏__E_STATIC_LIB来定义。
也就是说,如果是静态库那么这段代码就不会被编译。
静态库编译的时候只需在项目设置的C++ -> 预处理器 中加入 __E_STATIC_LIB 即可。

复制代码
  1. #ifndef __E_STATIC_LIB
  2. static LIB_INFO LibInfo =
  3. {
  4. /* { 库格式号, GUID串号, 主版本号, 次版本号, 构建版本号, 系统主版本号, 系统次版本号, 核心库主版本号, 核心库次版本号,
  5. 支持库名, 支持库语言, 支持库描述, 支持库状态,
  6. 作者姓名, 邮政编码, 通信地址, 电话号码, 传真号码, 电子邮箱, 主页地址, 其它信息,
  7. 类型数量, 类型指针, 类别数量, 命令类别, 命令总数, 命令指针, 命令入口,
  8. 附加功能, 功能描述, 消息指针, 超级模板, 模板描述,
  9. 常量数量, 常量指针, 外部文件} */
  10. LIB_FORMAT_VER, _T(LIB_GUID_STR),
  11. LIB_MajorVersion, LIB_MinorVersion, LIB_BuildNumber,
  12. LIB_SysMajorVer, LIB_SysMinorVer, LIB_KrnlLibMajorVer, LIB_KrnlLibMinorVer,
  13. _T(LIB_NAME_STR), __GBK_LANG_VER, _WT(LIB_DESCRIPTION_STR), _LIB_OS(__OS_WIN),
  14. _WT(LIB_Author), _WT(LIB_ZipCode), _WT(LIB_Address), _WT(LIB_Phone), _WT(LIB_Fax), _WT(LIB_Email), _WT(LIB_HomePage), _WT(LIB_Other),
  15. sizeof(DataTypes)/sizeof(DataTypes[0]), DataTypes, LIB_TYPE_COUNT, _WT(LIB_TYPE_STR), sizeof(Commands)/sizeof(Commands[0]), Commands, ExecuteCommand,
  16. NULL, NULL, mylib_ProcessNotifyLib, NULL, NULL,
  17. sizeof(Consts)/sizeof(Consts[0]), Consts, NULL
  18. };
  19. PLIB_INFO WINAPI GetNewInf()
  20. {
  21. return (&LibInfo);
  22. };
  23. #endif


注意: GetNewInf 是易语言动态库 (dll) 唯一必须导出的函数。所以需要在.def文件(mylib.def)里加入以下 

复制代码
  1. EXPORTS
  2.     ; 此处可以是显式导出
  3.     GetNewInf


接下来我们看看LIB_INFO 是如何定义的。具体含义可以参阅开发文档。这里根据库的不同,需要修改的地方有
1- LIB_ 这样的变量是我们另外定义的,可以定义在mylib.h中如下:
复制代码
  1. #ifndef __E_STATIC_LIB
  2. #define LIB_GUID_STR "0000000000000000000000000000" /*GUID串: {00000000-0000-0000-0000-00000000}, 必须使用guidgen.exe生成*/
  3. #define LIB_MajorVersion 1 /*库主版本号*/
  4. #define LIB_MinorVersion 1 /*库次版本号*/
  5. #define LIB_BuildNumber 20110318 /*构建版本号*/
  6. #define LIB_SysMajorVer 3 /*系统主版本号*/
  7. #define LIB_SysMinorVer 0 /*系统次版本号*/
  8. #define LIB_KrnlLibMajorVer 3 /*核心库主版本号*/
  9. #define LIB_KrnlLibMinorVer 0 /*核心库次版本号*/
  10. #define LIB_NAME_STR "支持库名称" /*支持库名*/
  11. #define LIB_DESCRIPTION_STR "支持库功能描述" /*功能描述*/
  12. #define LIB_Author "作者名称" /*作者名称*/
  13. #define LIB_ZipCode "邮政编码" /*邮政编码*/
  14. #define LIB_Address "通信地址" /*通信地址*/
  15. #define LIB_Phone "电话号码" /*电话号码*/
  16. #define LIB_Fax "传真号码" /*传真号码*/
  17. #define LIB_Email "电子邮箱" /*电子邮箱*/
  18. #define LIB_HomePage "主页地址" /*主页地址*/
  19. #define LIB_Other "其它信息" /*其它信息*/
  20. #define LIB_TYPE_COUNT 1 /*命令分类数量*/
  21. #define LIB_TYPE_STR "0000基本命令\0""\0" /*命令分类*/
  22. #endif


2- DataTypes 是库中定义的数据类型表,类型的数量可以自动由sizeof(DataTypes)/sizeof(DataTypes[0]) 计算。
Commands 函数命令信息表,ExecuteCommand 命令指针表,Consts 常量表 都是一样的。这些都是库中希望定义的成员。
如果不需要就在数量上写0,变量处替换成NULL即可。

3- mylib_ProcessNotifyLib 是库中需要定义的消息指针。必须定义在宏的外面以便静态和动态库都能调用
 
复制代码
  1. EXTERN_C INT WINAPI mylib_ProcessNotifyLib(INT nMsg, DWORD dwParam1, DWORD dwParam2)
  2. {
  3. #ifndef __E_STATIC_LIB
  4.   if(nMsg == NL_GET_CMD_FUNC_NAMES) // 返回所有命令实现函数的的函数名称数组(char*[]), 支持静态编译的动态库必须处理
  5.    return (INT)CommandNames;
  6.   else if(nMsg == NL_GET_NOTIFY_LIB_FUNC_NAME) // 返回处理系统通知的函数名称(PFN_NOTIFY_LIB函数名称), 支持静态编译的动态库必须处理
  7.    return (INT)"mylib_ProcessNotifyLib";
  8.   else if(nMsg == NL_GET_DEPENDENT_LIBS) return (INT)NULL;
  9.                 // 返回静态库所依赖的其它静态库文件名列表(格式为\0分隔的文本,结尾两个\0), 支持静态编译的动态库必须处理
  10.                 // kernel32.lib user32.lib gdi32.lib 等常用的系统库不需要放在此列表中
  11.                 // 返回NULL或NR_ERR表示不指定依赖文件  
  12. #endif
  13. return ProcessNotifyLib(nMsg, dwParam1, dwParam2);
  14. };


本函数的作用是接收来自易语言IDE或者运行时环境的通知。并且在编译的时候起到在静态库和动态库之间通讯的目的。


接下来我们就可以定义库中需要使用的 函数,类型,常量 了。
这些都定义在 mylib_ProcessNotifyLib 函数的前面,且都定义在宏中,如下:
#ifndef __E_STATIC_LIB
...
#endif
因为这些只需包含在动态模块里,不需要静态中定义。 函数的具体实现过程需要定义在宏的外面,具体方式会在下文中讲到。

2) 定义常量 Consts

复制代码
  1. #ifndef __E_STATIC_LIB
  2. LIB_CONST_INFO Consts[] =
  3. {
  4. /* { 中文名称, 英文名称, 常量布局, 常量等级(LVL_), 参数类型(CT_), 文本内容, 数值内容 } */
  5. { _WT("常量_ZERO"), _WT("ZERO"), NULL, LVL_SIMPLE, CT_NUM, NULL, 0 },//数值常量
  6. { _WT("常量_TEST"), _WT("TEST"), NULL, LVL_HIGH, CT_TEXT, "TEST", NULL }//文本常量
  7. };
  8. #endif


常量等级有: LVL_SIMPLE          1        // 初级
                      LVL_SECONDARY       2        // 中级
                      LVL_HIGH            3        // 高级

参数类型有: CT_NUM             1    // sample: 3.1415926
                      CT_BOOL            2    // sample: 1
                      CT_TEXT            3    // sample: "abc"

文本内容是CT_TEXT用,数值内容是CT_NUM和CT_BOOL用。

3) 定义数据类型 DataTypes

用作提供支持库自定义数据类型,包含窗口单元。一个简单的例子:

复制代码
  1. #ifndef __E_STATIC_LIB
  2. INT DatatypeCommandIndexs[] =
  3. {
  4. 2
  5. };
  6. static LIB_DATA_TYPE_INFO DataTypes[] =
  7. {
  8. /* { 中文名称, 英文名称, 数据描述, 索引数量, 命令索引, 对象状态, 图标索引, 事件数量, 事件指针, 属性数量, 属性指针, 界面指针, 元素数量, 元素指针 } */
  9. { _WT("数据类型命令"), _WT("DatatypeCommand"), _WT("测试数据类型命令。"), sizeof(DatatypeCommandIndexs)/sizeof(DatatypeCommandIndexs[0]), DatatypeCommandIndexs, NULL, 0, 0, NULL, 0, NULL, NULL, 0, NULL }
  10. };
  11. #endif


关于LIB_DATA_TYPE_INFO的解释 以及 窗口型数据的定义 都可参见开发文档中 "m_pDataType成员说明"和"数据类型说明"。


4) 定义函数,ExecuteCommand,Commands

函数书写规范是
复制代码
  1. EXTERN_C void mylib_函数名(PMDATA_INF pRetData, INT iArgCount, PMDATA_INF pArgInf)
  2. {
  3. ...
  4. };


函数的实现都需要定义在宏的外面以便静态和动态库都能使用,但ExecuteCommand,Commands则只需定义在宏的里面供动态库使用。
pRetData 输出数据指针。当对应CMD_INFO中m_dtRetType为_SDT_NULL(即定义无返回值)时,pRetData无效;
iArgCount 函数参数个数
pArgInf 函数参数指针


复制代码
  1. #ifndef __E_STATIC_LIB
  2. PFN_EXECUTE_CMD ExecuteCommand[] =
  3. {
  4. mylib_函数名 // 所有需要库中调用的函数都列在这里,用逗号隔开
  5. };
  6. static const char* const CommandNames[] =
  7. {
  8. "mylib_函数名" // 所有需要库中调用的函数名都写在这里,用逗号隔开
  9. };
  10. ARG_INFO CommandArgs[] =
  11. {
  12. /* { 参数名称, 参数描述, 图像索引, 图像数量, 参数类型(参见SDT_), 默认数值, 参数类别(参见AS_) } */
  13. { _WT("参数1"), _WT("本命令的参数1"), 0, 0, SDT_INT, NULL, NULL } //函数参数数组定义写在这里,每个{}为一个参数的表述,用逗号隔开
  14. };
  15. static CMD_INFO Commands[]=
  16. {
  17. /* { 中文名称, 英文名称, 对象描述, 所属类别(-1是数据类型的方法), 命令状态(CT_), 返回类型(SDT_), 此值保留, 对象等级(LVL_), 图像索引, 图像数量, 参数个数, 参数信息 } */
  18. { _WT("函数名"), _WT("英文函数名"), _WT("函数功能描述"), 1, NULL, SDT_BOOL, 0, LVL_SIMPLE, 0, 0, 1, CommandArgs },//基本命令
  19. };
  20. #endif


注:
a. 函数名前的前缀 mylib_ 是以后静态库中使用的。要求必须是动态库项目名称mylib的全小写形式 mylib_。
b. 只需对库中需要调出的函数加前缀处理,其他函数不需要这样书写。
c. 如果程序内部需要调用这个函数,只需使用函数名即可,无须前缀。
d. 参数类型如果是 AS_RECEIVE_VAR或AS_RECEIVE_VAR_ARRAY或AS_RECEIVE_VAR_OR_ARRAY 则参数必须是变量。
// AS_DEFAULT_VALUE_IS_EMPTY  参数可空且默认值为空
// AS_HAS_DEFAULT_VALUE 参数有默认值 且不可空
// AS_RECEIVE_VAR 参数必须是非数组变量
// AS_RECEIVE_VAR_OR_ARRAY 参数是数组或非数组变量
// AS_RECEIVE_ARRAY_DATA 参数是数组数据
// AS_RECEIVE_ALL_TYPE_DATA 参数是数组或非数组数据
以上参数除了前两个互斥,其他都可以相加使用,以便具有多个性质。
例如 AS_DEFAULT_VALUE_IS_EMPTY + AS_RECEIVE_VAR 表示参数可空,并且只能是变量。
e. 所属类别是在库中函数归类的子目录,这些子目录的名字在 LIB_INFO的LIB_TYPE_STR 字串定义。-1是数据类型,1第一类,2第二类...

sdk中关于数据类型的定义如下: 
    #define        _SDT_NULL        0           // 空白数据类型
    #define        _SDT_ALL         MAKELONG (MAKEWORD (0, 0), 0x8000)  // 通用型

        /*  仅用于支持库命令定义其参数或返回值的数据类型,当用于定义库命令参数时,
        _SDT_ALL可以匹配所有数据类型(数组类型必须符合要求)。*/
    #define        SDT_BYTE         MAKELONG (MAKEWORD (1, 1), 0x8000)  // 字节
    #define        SDT_SHORT        MAKELONG (MAKEWORD (1, 2), 0x8000)  // 短整数
    #define        SDT_INT          MAKELONG (MAKEWORD (1, 3), 0x8000)  // 整数
    #define        SDT_INT64        MAKELONG (MAKEWORD (1, 4), 0x8000)  // 长整数
    #define        SDT_FLOAT        MAKELONG (MAKEWORD (1, 5), 0x8000)  // 小数
    #define        SDT_DOUBLE       MAKELONG (MAKEWORD (1, 6), 0x8000)  // 双精度小数
    #define        SDT_BOOL         MAKELONG (MAKEWORD (2, 0), 0x8000)  // 逻辑
    #define        SDT_DATE_TIME    MAKELONG (MAKEWORD (3, 0), 0x8000)  // 日期时间
    #define        SDT_TEXT         MAKELONG (MAKEWORD (4, 0), 0x8000)  // 文本
    #define        SDT_BIN          MAKELONG (MAKEWORD (5, 0), 0x8000)  // 字节集
    #define        SDT_SUB_PTR      MAKELONG (MAKEWORD (6, 0), 0x8000)  // 记录用户易语言子程序的代码地址

这些数据类型在函数定义参数时调用。

动态库制作完成后,编译会生成mylib.dll文件。把.dll改成.fne 拷贝到易语言的lib文件目录下即可使用。或者也可以修改项目属性,把编译输出文件后缀从.dll修改成.fne,并输出在易语言的lib目录中。 这样编译完后即可直接在易语言里调用。


II. 静态库的制作

如果你已经按照上面的方法书写代码并制作好了动态库,接着就可以方便的再此基础上制作静态库了。方法有两种
第一种是生成一个静态库项目编译
第二种是在原来的动态库项目上修改成静态库项目

方法一)生成静态库项目
具体步骤如下:
1. 在项目解决方案上鼠标右键 -> 添加 -〉新建项目 名称输入 mylib_static (就是动态库项目名称加后缀_static)。
VS的向导里设置程序类型 为"静态库"。去掉预编译头的钩。点击完成。

2. 选择动态库项目文件列表中的所有文件,ctrl+C 复制 在新的mylib_static项目 中ctrl+V拷贝过来。

3. 配置mylib_static 项目属性, 以release模式为例,打开release配置。修改配置如下:
+ 常规 -> 字符集 设置为多字节字符集
+ 常规 -> 全程序优化 设成 无全程序优化 (这里很重要否则会影响 resym.exe 的工作)
+ C++选项卡 -> 附加包含目录 填入D:\E51\sdk\cpp\ELib
+ C++ -> 预处理器 -> 预处理定义 添加宏 __E_STATIC_LIB
+ 生成事件 -> 生成后事件 -> 命令行 填入 D:\E51\sdk\tools\resym.exe all infile=$(TargetPath) outfile=$(TargetPath)
resym.exe 是用来修改lib库连接符号的,以解决连接时符号冲突的问题。程序位置设成你自己sdk所在位置。

设置后选择release编译即可。 编译完后会生成静态库mylib_static.lib文件。

方法二)修改动态库配置为静态库配置
具体步骤如下:
打开动态库项目mylib的项目管理,点击配置管理器,mylib的配置处下拉菜单选择 "新建", 添入名称 release_static, "从此处复制设置"选择release
创建release_static后开始修改配置如下:
+ 常规 -> 配置类型 设置为 静态库(.lib)
+ 常规 -> 全程序优化 设成 无全程序优化
+ C++ -> 预处理器 -> 预处理定义 删除宏 _USRDLL 添加宏 __E_STATIC_LIB
+ C++ -> 预编译头 -> 选择不使用预编译头
+ 管理员 -> 常规 -> 输出文件 改为 $(OutDir)\$(ProjectName)_static.lib
+ 生成事件 -> 生成后事件 -> 命令行 填入你 D:\E51\sdk\tools\resym.exe all infile=$(TargetPath) outfile=$(TargetPath)

设置修改完成后,选择release_static项目编译

静态库的使用需要动态库支持。我们需要把动态库的fne放在易语言的lib目录下 和 静态库的lib放在static_lib目录下。这样才能静态编译。编译出来的结果将可以脱离任何非系统支持库独立运行。

关于运行时库的配置:

个人比较喜欢把release模式设置成"在静态库中使用 MFC"并且使用"多线程(/MT)"。
VS向导生成的MFC项目(exe,dll,lib)一般都默认设置为 "在共享 DLL 中使用 MFC" 并使用 "多线程 DLL (/MD)"
这样编译出来的COFF文件尺寸小,但程序运行时必须依赖MFC的dll库。
把设置修改成"在静态库中使用 MFC"并且使用"多线程(/MT)" 就可以脱离MFC的dll库运行。这样即使在没有安装Visual C++ Runtime library的机器上也能正常运行。这种模式也就是VC++的"静态编译"。编译后的文件尺寸会稍大些。技术上和易语言的静态编译是一样的。

具体设置方法
+ 常规 -> MFC的使用 选择 "在静态库中使用 MFC",如果库中没有用到MFC的类函数和类资源 那么也可以选择"使用标准 Windows 库"
+ C++ -> 代码生成 -> 运行时库 选择 "多线程(/MT)"

很多VC软件开发者就是因为这里没有设置好,结果程序在其他机器上一运行就跳出缺少运行时库的错误提示。所以本人建议最好养成习惯,使用静态编译模式配置项目。




下面给出一个简单的支持库的例子:

我们希望库里面有一个函数,且不需要自定义数据类型和常量。
函数中文名称是 "两数相加",英文名称是"myadd", 希望调用格式是。
〈小数型〉 两数相加 (小数型 参数1,小数型 参数2)

该函数在库中所属函数分类是"基本运算"

源代码如下:

+ mylib.cpp文件内容

复制代码
  1. #include "stdafx.h"
  2. #include "mylib.h"
  3. #include <lib2.h>
  4. #include <lang.h>
  5. #include <fnshare.h>
  6. #include <fnshare.cpp>
  7. //
  8. // 模块内容
  9. //
  10. //定义函数
  11. EXTERN_C void mylib_myadd(PMDATA_INF pRetData, INT iArgCount, PMDATA_INF pArgInf)
  12. {
  13. pRetData->m_float = pArgInf[0].m_float + pArgInf[1].m_float;
  14. };
  15. /
  16. #ifndef __E_STATIC_LIB
  17. PFN_EXECUTE_CMD ExecuteCommand[] =
  18. {
  19. mylib_myadd // 所有需要库中调用的函数都列在这里,用逗号隔开
  20. };
  21. static const char* const CommandNames[] =
  22. {
  23. "mylib_myadd" // 所有需要库中调用的函数名都写在这里,用逗号隔开
  24. };
  25. ARG_INFO CommandArgs[] =
  26. {
  27. /* { 参数名称, 参数描述, 图像索引, 图像数量, 参数类型(参见SDT_), 默认数值, 参数类别(参见AS_) } */
  28. { _WT("参数1"), _WT("加数1,小数型"), 0, 0, SDT_FLOAT, NULL, NULL }, //函数参数数组定义写在这里,每个{}为一个参数的表述,用逗号隔开
  29. { _WT("参数2"), _WT("加数2,小数型"), 0, 0, SDT_FLOAT, NULL, NULL } //函数参数数组定义写在这里,每个{}为一个参数的表述,用逗号隔开
  30. };
  31. static CMD_INFO Commands[]=
  32. {
  33. /* { 中文名称, 英文名称, 对象描述, 所属类别(-1是数据类型的方法), 命令状态(CT_), 返回类型(SDT_), 此值保留, 对象等级(LVL_), 图像索引, 图像数量, 参数个数, 参数信息 } */
  34. { _WT("两数相加"), _WT("myadd"), _WT("两个小数相加求和,返回小数"), 1, NULL, SDT_FLOAT, 0, LVL_SIMPLE, 0, 0, 2, CommandArgs },//基本命令
  35. };
  36. #endif
  37. //
  38. EXTERN_C INT WINAPI mylib_ProcessNotifyLib(INT nMsg, DWORD dwParam1, DWORD dwParam2)
  39. {
  40. #ifndef __E_STATIC_LIB
  41.   if(nMsg == NL_GET_CMD_FUNC_NAMES)
  42.    return (INT)CommandNames;
  43.   else if(nMsg == NL_GET_NOTIFY_LIB_FUNC_NAME)
  44.    return (INT)"mylib_ProcessNotifyLib";
  45.   else if(nMsg == NL_GET_DEPENDENT_LIBS)
  46.    return (INT)NULL;
  47. #endif
  48. return ProcessNotifyLib(nMsg, dwParam1, dwParam2);
  49. };
  50. #ifndef __E_STATIC_LIB
  51. static LIB_INFO LibInfo =
  52. {
  53. /* { 库格式号, GUID串号, 主版本号, 次版本号, 构建版本号, 系统主版本号, 系统次版本号, 核心库主版本号, 核心库次版本号,
  54. 支持库名, 支持库语言, 支持库描述, 支持库状态,
  55. 作者姓名, 邮政编码, 通信地址, 电话号码, 传真号码, 电子邮箱, 主页地址, 其它信息,
  56. 类型数量, 类型指针, 类别数量, 命令类别, 命令总数, 命令指针, 命令入口,
  57. 附加功能, 功能描述, 消息指针, 超级模板, 模板描述,
  58. 常量数量, 常量指针, 外部文件} */
  59. LIB_FORMAT_VER, _T(LIB_GUID_STR),
  60. LIB_MajorVersion, LIB_MinorVersion, LIB_BuildNumber,
  61. LIB_SysMajorVer, LIB_SysMinorVer, LIB_KrnlLibMajorVer, LIB_KrnlLibMinorVer,
  62. _T(LIB_NAME_STR), __GBK_LANG_VER, _WT(LIB_DESCRIPTION_STR), _LIB_OS(__OS_WIN),
  63. _WT(LIB_Author), _WT(LIB_ZipCode), _WT(LIB_Address), _WT(LIB_Phone), _WT(LIB_Fax), _WT(LIB_Email), _WT(LIB_HomePage), _WT(LIB_Other),
  64. 0, NULL, LIB_TYPE_COUNT, _WT(LIB_TYPE_STR), sizeof(Commands)/sizeof(Commands[0]), Commands, ExecuteCommand,
  65. NULL, NULL, mylib_ProcessNotifyLib, NULL, NULL,
  66. 0, NULL, NULL
  67. };
  68. PLIB_INFO WINAPI GetNewInf()
  69. {
  70. return (&LibInfo);
  71. };
  72. #endif


+ mylib.h的文件里加入

复制代码
  1. #ifndef __E_STATIC_LIB
  2. #define LIB_GUID_STR "9D13FF9D0E1240aaBE1B78E6B32B855F" /*GUID串: {9D13FF9D-0E12-40aa-BE1B-78E6B32B855F}, 必须使用guidgen.exe生成*/
  3. #define LIB_MajorVersion 1 /*库主版本号*/
  4. #define LIB_MinorVersion 1 /*库次版本号*/
  5. #define LIB_BuildNumber 20110410 /*构建版本号*/
  6. #define LIB_SysMajorVer 3 /*系统主版本号*/
  7. #define LIB_SysMinorVer 0 /*系统次版本号*/
  8. #define LIB_KrnlLibMajorVer 3 /*核心库主版本号*/
  9. #define LIB_KrnlLibMinorVer 0 /*核心库次版本号*/
  10. #define LIB_NAME_STR "我的易库" /*支持库名*/
  11. #define LIB_DESCRIPTION_STR "测试易库制作" /*功能描述*/
  12. #define LIB_Author "kaien" /*作者名称*/
  13. #define LIB_ZipCode "" /*邮政编码*/
  14. #define LIB_Address "" /*通信地址*/
  15. #define LIB_Phone "" /*电话号码*/
  16. #define LIB_Fax "" /*传真号码*/
  17. #define LIB_Email "[email]kaienfr@gmail.com[/email]" /*电子邮箱*/
  18. #define LIB_HomePage "" /*主页地址*/
  19. #define LIB_Other "祝大家使用愉快" /*其它信息*/
  20. #define LIB_TYPE_COUNT 1 /*命令分类数量*/
  21. #define LIB_TYPE_STR "0000基本运算\0""\0" /*命令分类*/
  22. #endif



常见问题:

Q: 编译静态库没问题,但是易语言调用静态编译时出现
error LNK2001: unresolved external symbol ___security_cookie
error LNK2001: unresolved external symbol @__security_check_cookie@4

A: 关掉“缓冲区安全检测”重新编译静态库。 具体方法:
静态库编译项目设置里,C++ -> 代码生成 -> 缓冲区安全检测 设置为 否 重新编译静态库即可。

Q: 如果你的静态库在静态编译的时候需要其他静态库的支持 怎么办?

A: 例如: 你的静态库A.lib里使用了其他静态库B.lib和C.lib的函数。
那么你需要修改A源码里的函数mylib_ProcessNotifyLib的
  else if(nMsg == NL_GET_DEPENDENT_LIBS)
   return (INT)"B.lib\0""C.lib\0""\0";
  // 返回静态库所依赖的其它静态库文件名列表(格式为\0分隔的文本,结尾两个\0)

相应的编译动态库时,需要把 B.lib;C.lib 加入到项目属性的
连接器 -> 输入 -> 附加依赖项 里。也就是使用静态库编译dll和exe的方法。

Q: 如何调试你的动态库?

A: VC上调试你的动态库和调试dll是一样的。具体步骤是:
1. debug模式编译出动态库fne/fnr文件,放到lib目录下
2. 易语言写个测试程序,里面调用这个动态库某个需要调试的函数
3. 动态编译这个测试程序,加入是test.exe
4. VC中在需要调试的调试函数开头处设断点,然后F5运行调试
5. 选择test.exe文件,执行。一旦测试程序运行到这个函数,就会断下来,我们就可以调试了。
只要动态库运行正常了,静态库因为用的是同一套代码,所以也没问题。

Q: 待续...

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
F:\ISO\=]易语言视频[=模块[=\易语言支持\[外挂海外挂海E模块2.2.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\15353个常量支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\ADODB数据操作支持 (1.4#3版).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\detours支持1.0.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\eIme支持静态版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\elib++ (静态版).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\eLIB++EX (1.3#0版)静态版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\elib++EX1.3 支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\ELIBCP.fne ver 1.0.2支持静态编译 编译时间2010-10-29.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\ET助手1.08.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\FAST CGI 支持,支持静态编译.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\GBB的线程支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\GIF动画全操作支持1.1版(伪静态).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\HGE游戏引擎支持下载(支持静态编译).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\IOCP服务器模型支持1.6稳定版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\IO交互支持,支持静态编译.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\JSON支持 2.2(3.26更新).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\Lookhandles2.3(句柄查看精灵).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\lua扩展支持静态版.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\Md5加密支持 (1.1#3版) - 静态版.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\mew11加壳工具.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\mp3信息支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\MT支持测试版10.23.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\NB水波特效支持(静态).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\PDF电子书阅读支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\PE加载器(PeLoader)支持版.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\QQ常用功能支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\Sqlite3支持 - 公开测试版 [2012-5-2].zip F:\ISO\=]易语言视频[=模块[=\易语言支持\SSK皮肤支持(附带皮肤96个).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\SWF制作支持1.1(静态版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\tooltip.lpk F:\ISO\=]易语言视频[=模块[=\易语言支持\vclbase支持(静态版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\WEBUI支持1.1静态.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\WEB客户支持2.3支持对json解析(支持静态).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\WonderWall内联汇编支持(11-28).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\XM音乐播放支持支持静态编译).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\xwxyh无限扩展 (1.0#1版)静态版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\标准aes加密解密支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\操作系统界面功能支持(PB版) (1.0#50版) 静态版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\常量支持(静态版)--2010-1-27更新.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\常量支持开源(VC6版).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\常用加解密支持支持静态)-2010-4-21升级.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\超级加解密支持 (1.1#0版)静态版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\超级加解密支持1.0#3(08.11.1).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\超文本浏览框 - 公开测试版 [2012-5-2].zip F:\ISO\=]易语言视频[=模块[=\易语言支持\超文本浏览框支持 安全版3.2(2012-04-25)泪闯天涯.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\磁盘文件操作支持V1.1(静态版).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\大鸟的精灵助手支持--静态版.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\大鸟的目录树支持--静态版(二次修正).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\大鸟的目录树支持--静态版.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\大鸟的网络套接字支持静态版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\点菜宝PDA接口支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\电话语音支持1.0#4版公开测试.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\动态链接辅助支持v1.0.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\动态选择夹支持 (1.1#2版).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\多文档界面(MDI)支持 MFC版 6.3--静态版.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\辅助支持PLUSA(2011.4.23).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\高级表格支持最新测试版 2012-7-24.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\高级表格支持最新测试版(2012-11-2).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\高级查询条件支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\黑月OCX组件驱动支持_(1.0#0版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\互联网服务支持(ISAPI) - 公开测试版3(2012-5-29).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\互联网浏览器支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\彗星网页操作支持(支持静态编译).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\彗星小助手.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\基于黑月的COM编译支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\简易模块3.0.ec F:\ISO\=]易语言视频[=模块[=\易语言支持\简易模块3.1.ec F:\ISO\=]易语言视频[=模块[=\易语言支持\界面增强支持1.4静态版.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\局域网操作支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\酷哥win7 flash支持1.6#5.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\快播支持修改版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\扩展功能支持一 (3.0#0版)逆向源代码.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\蓝牙操作支持 NPK格式.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\雷软通用支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\目录文件.txt F:\ISO\=]易语言视频[=模块[=\易语言支持\内存DLL操作支持)含例子源码和演示录像.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\闪电易支持 2.4#4.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\视频播放支持(测试版) (1.0#0版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\手机短信操作支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\手机短信设备支持(Phone.fne).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\数据操作支持2.7 - 最新测试版(2012-7-10).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\数据权限管理支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\数值运算支持 - 公开测试版(2012-4-24).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\特殊功能支持(2012-5-22).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\提示工具支持的静态版 1.1.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\同步缩放控件.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\托盘图标支持2.01版,支持静态编译.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\网络传送支持 - 公开测试版(2012-5-9).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\网络套接字支持(NSocket),静态,黑月,2011.11.18更新.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\网络通讯支持 - 最新修正版(2012-5-12).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\系统辅助支持1.3正式版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\线程池支持(含源码).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\新LUA支持 1.0#0版+例程源码 傻瓜化应用.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\鑫宇反调试支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\虚表支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\异形支持2.0,已支持静态编译.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\易IDE插件支持1.2.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\易语言.尘土 支持支持静态编译.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\易语言Detours支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\易语言核心支持最新修正测试版 - 201287.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\易语言特殊命令支持 1.41更新.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\幽日清風]双子物语网络功能支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\袁松的支持1.0(静态版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云的ADO数据操作支持(1.2#1版).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\云的大漠插件辅助支持 (2.3#1版)静态版.7z F:\ISO\=]易语言视频[=模块[=\易语言支持\云的代码编辑框支持 (1.1#0版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云的丰富文本框支持 (1.0#0版)2012-11-13.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云的后台键盘鼠标支持(1.0#0版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云的图像处理支持1.1(支持静态编译).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云的真视3D游戏引擎支持 (1.1#0版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云的注册算法支持 (1.1#0版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云皮肤魔法师支持 (1.2#0版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云外归鸟的MDI窗口支持 (2.1#0版)静态版.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\云外归鸟的PDF文档浏览器 (1.1#0版)支持伪静态编译.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\云外归鸟女声朗读支持(1.2#1静态版).zip F:\ISO\=]易语言视频[=模块[=\易语言支持\杂项支持--修改自凌晨孤星(支持静态).rar F:\ISO\=]易语言视频[=模块[=\易语言支持\正态分布图像处理支持1.03.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\支持静态编译的XM音乐播放支持.zip F:\ISO\=]易语言视频[=模块[=\易语言支持\指针操作支持.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\指针操作支持2.0.rar F:\ISO\=]易语言视频[=模块[=\易语言支持\转换编码支持静态.zip 。。。。。。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值