如何将C语言打包成库
一般来说,C不能直接调用C函数库,只有将C函数库封装成C接口后才能调用C。
以下示例说明了一种封装策略:
//add . cxx中的代码
#包含“add.h”
int sample::方法()
{
cout "方法被调用!\ n ";
}
add.h中的代码
#包括
使用命名空间std
班级样本
{
公共:
int方法();
};
将上述两个文件生成动态库libadd.so放入/usr/lib目录,编译命令如下:
sudo g-fpic-shared-g-o/usr/lib/libadd . so add . cxx-I ./
因为C中无法识别该类,所以上述类的成员函数必须封装到C接口函数中才能调用。接下来,进行封装,将输出接口转换为C接口。
mylib.cxx中的代码
#包含“add.h”
#ifndef _cplusplus
#define _cplusplus
#包含“mylib.h”
#endif
int myfunc()
{
样本ss;
ss . method();
返回0;
}
//mylib . h中的代码
#ifdef _cplusplus
外部“C”
{
#endif
int my func();
#ifdef _cplusplus
}
#endif
在linux下,gcc编译器不使用变量_cplusplus来区分C代码和C代码(没有宏定义)。如果使用gcc编译器,我们可以在这里定义一个变量_cplusplus来区分C代码和C代码,所以我们在mylib.cxx中定义一个变量_cplusplus来标识是否需要“extern”C”来将函数接口封装成C接口。但是,如果使用G编译器,就不需要定义_cplusplus。编译命令如下:
g-fpic-shared-g-o mylib . so mylib . cxx-la-I ./
主网站
#包括
#包括
#包含“mylib.h”
(同Internationalorganizations)国际组织
主()
{
int(* dl func)();
void *句柄;//定义句柄
handle = dlopen("。/mylib.so ",RTLD _ LAZY);//获取库句柄
dlfunc = dlsym(handle," my func ");//获取函数入口
(* dl func)();
dlclose(句柄);
返回0;
}
编译命令如下:
gcc -o main main。/mylib.so -ldl
下面可以执行。
需要注意的是,main.c和mylib.cxx都需要包含mylib.h,它需要“extern”C”将函数myfunc封装到C接口的函数输出中,而C不识别“extern”C”,所以需要定义_cplusplus来区别对待mylib.h中的函数myfunc。
也可以在main.c的main函数中直接调用myfunc()函数来执行,本文一般介绍调用库函数的方法。
C语言:如何自己制作库函数? 一个简单的例子,但是程序编译的基本思想都在里面,需要你自己去体验和查资料。
请遵循以下步骤
-
步骤1:我的电脑-属性-高级-环境变量
添加3个变量
1.名称:路径值:vc的安装目录包含cl.exe的bin目录路径vc目录下包含mspdb80.dll的目录路径。
比如我的是D:\ Program Files \ Microsoft Visual Studio 8 \ VC \ bin;d:\ Program Files \ Microsoft Visual Studio 8 \ common 7 \ IDE;
2.名称:include值:vc安装目录下的include目录,主要是查找头文件。我的是D:\ program files \ Microsoft Visual Studio 8 \ VC \ include;d:\ Program Files \ Microsoft Visual Studio 8 \ VC \ platform SDK \ Include;
3.名称:lib值:vc目录下包含库文件的目录路径。
我的是d:\ program files \ Microsoft Visual Studio 8 \ VC \ lib;d:\ Program Files \ Microsoft Visual Studio 8 \ VC \ platform SDK \ Lib;
第二步:你需要以下两个文件。
// - libdemo.c
#包含stdio.h
void lib_func()
{
printf(" lib中的这个例程\ n ");
}
// - main.c
void lib _ func();
int main(int argc,char *argv[])
{
lib _ func();
}
第三步:命令
Cl /c libdemo.c '编译libdemo.c以生成libdemo.obj
' Lib libdemo.obj '生成libdemo.lib库文件。
'编译main.c。
Link main.obj libdemo.lib '生成main.obj。
-
呵呵,补充一下。见4楼建议。如果是做DLL,COM组件就不做了,有点复杂。
1。稍微修改一下libdemo.c
// - libdemo.c
#包含stdio.h
_ _ declspec(dll export)void lib _ func()
{
printf(" lib中的这个例程\ n ");
}
2。命令
cl /c libdemo.c main.c
链接libdemo.obj /dll '以生成libdemo.lib
link main.obj libdemo.lib
如何将C语言中常用的函数打包成编译器的库函数? 使用编译器提供的库管理工具。
C语言的编译器会提供一个命令行工具,可以添加编译好的。obj模块到指定的库文件,以后使用时只需要连接库文件。这个命令行工具通常是lib.exe。使用此工具,您可以查看库中的模块,向库中添加模块,以及从库中删除模块。这个工具不仅是一个自己构建的库文件的管理工具,还可以管理所有的库文件,包括C语言提供的标准库。
如何制作一个C语言函数库 第一,创建lib库;
建议用VC更方便,以VC2005为例:
新项目Win32控制台应用程序静态库已完成。
然后在里面写一个函数,编译库。
为外部函数创建新的头文件声明;
二,lib库的使用
通过创建一个新程序,然后引用上面的头文件,可以使用库中的函数。然后将lib库添加到项目配置中:属性链接器输入附加的依赖项,并填写您的lib库。您可以添加路径。那么编译应该就够了。
祝你好运!
如何将C程序打包成DLL 用VC写DLL教程
用Visual Sudio 6.0创建一个新项目。项目类型是Win32动态链接库。项目名称是任意的,所有其他选项都是默认的。
使用以下代码创建一个新的cpp文件:
int add(int a,int b){
返回a b;
}
如果项目类型是Win32控制台应用程序,编译链接后,将生成一个调试目录,其中包含一个exe文件。
这里我们的项目类型是Win32动态链接库。编译完链接后,我们希望生成一个调试目录,其中包含一个dll文件。
情况就是这样。
我们可以用depends工具打开这个dll文件,看看它导出了什么函数。
“依赖”工具位于“工具”菜单下。其实就是D:\ program files \ Microsoft Visual Studio \ common \ tools下的一个文件。
我们发现这个dll没有导出任何东西。
这是因为我们没有指定要导出的内容。默认情况下,cpp中的函数不会被导出,因为它们可能只是我们想要导出的函数所调用的“内部函数”。
要导出一个函数,我们需要添加_declspec(dllexport),代码变成:
int _ declspec(dll export)add(int a,int b){
返回a b;
}
再次链接
再看dll文件找一个?添加@@YAHHH@Z函数。这似乎很奇怪,但我终于明白了一些事情。
现在让我们测试这个dll。
创建一个新项目,并选择Win32控制台应用程序作为类型。
使用以下代码创建一个新的cpp文件
#包含iostream.h
#包含Windows.h
void main(){
typedef int (*ADD)(int,int);//函数指针类型
h instance Hint =::LoadLibrary(" dll . dll ");//加载我们刚刚生成的dll。
ADD add = (ADD)GetProcAddress(提示,“ADD”);//获取dll导出的add方法。
coutadd(3,4)endl;
}
其中LoadLibrary是Windows.h中声明的函数
编译链接,没问题。
快跑。错误!
分析一下,程序怎么知道去哪里找我们的dll?
它会按以下顺序搜索:当前可执行模块所在的目录,当前目录,Windows系统目录,Windows目录。GetWindowsDirectory函数检索该目录的路径,该目录在PATH环境变量中列出。
因此,在运行测试项目之前,我们需要将dll复制到这个测试项目的调试目录中。
还是有错!
我们来分析一下。我们刚才看到的是一个叫。添加@@YAHHH@Z函数。那么,是这个原因吗?
将代码更改为:
#包含iostream.h
#包含Windows.h
void main(){
typedef int (*ADD)(int,int);//函数指针类型
h instance Hint =::LoadLibrary(" dll . dll ");//加载我们刚刚生成的dll。
ADD add = (ADD)GetProcAddress(提示,"?加@ @ YAHHH @ Z ");//获取dll导出的add方法。
coutadd(3,4)endl;
}
再次编译链接,运行,成功了!
那么如何才能正确的导出我们函数的名字呢?
将extern“C”添加到生成dll的项目的代码中,并将其更改为:
extern " C " int _ declspec(dll export)add(int a,int b)...{
返回a b;
}
编译完链接后,查看dll文件,可以看到导出的函数变成了add。
至此,下面的代码可以正常工作了。
#包含iostream.h
#包含Windows.h
void main()...{
typedef int (*ADD)(int,int);//函数指针类型
h instance Hint =::LoadLibrary(" dll . dll ");//加载我们刚刚生成的dll。
ADD add = (ADD)GetProcAddress(提示,“ADD”);//获取dll导出的add方法。
coutadd(3,4)endl;
}
除了用_declspec(dllexport)来表示要导出的函数,用extern“C”来修正名称,我们还可以用一个. def文件来达到上述目的。
在dll项目中创建新文件,选择文本文件作为类型,并添加后缀。顾名思义。
内容如下:
图书馆
出口
增加
剩下的步骤和之前一样。
例如,您也可以使用def文件更改导出函数的名称
图书馆
出口
myadd =添加
以便导出的函数被称为myadd而不是add。
您也可以为该函数分配一个序列号。
比如:
图书馆
出口
myadd=add @4
Myadd被分配了一个序列号。
在测试项目中,我们可以根据序列号得到我们的函数:
#包含iostream.h
#包含Windows.h
void main(){
typedef int (*ADD)(int,int);
h instance h instance =::LoadLibrary(" dll . dll ");
ADD ADD =(ADD)GetProcAddress(h instance,MAKEINTRESOURCE(4));//根据序列号获取函数
coutadd(3,4)endl;
ADD =(ADD)GetProcAddress(h instance," myadd ");//在def文件中指定的名称
coutadd(3,4)endl;
free library(h instance);//释放加载的dll文件所占用的资源。
}
以上是关于运行时动态加载dll,以下是关于启动时动态加载dll。
生成dll的项目不用改,还是上面那个(名字是myadd,序列号是4)。
将测试代码更改为:
//首先将DLL.lib文件复制到项目目录中。
#包含iostream.h
#pragma注释(lib,“DLL.lib”)
extern int myadd(int,int);//只添加上面这句话而不添加这句话(或者在项目设置中添加DLL.lib)会导致链接错误。
void main()
{
coutmyadd(3,4)endl;
}
这个方法调用dll,链接时会包含我们exe中要引用的符号,启动程序时会加载所有需要的dll。
#pragma comment(lib,“DLL.lib”)指明使用哪个DLL,在Debug中可以找到哪个DLL.lib。我们还需要将DLL.lib复制到测试项目目录(不是调试目录)。我们也可以将它添加到项目属性中。方法是项目-设置-链接链接,在对象/库模块末尾添加DLL.lib。
extern int add(int,int);指出我们的add是一个外部函数,在本文档中没有定义。
最后强调,复制的文件要复制到正确的地方。
当生成的dll文件和我说的不一致时,尽量选择Build-Rebuild All。
最后更新于 2023-10-07 17:20:22 并被添加「」标签,已有 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
相关文章