如何将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。

相关文章

发表新评论