由C++生成C接口函数库方法
- 格式:doc
- 大小:26.00 KB
- 文档页数:2
qt默认的编程语言为C++语言。
如果你用qt编译.c文件,会出现找不到C语言的默认头文件等错误(如:stdio.h等)。
qt中不支持extern "C"{}的这种写法,我前几天有一个C程序需要移植到Qt的工程中,本希望直接extern "C"就ok了,但发现qt4居然不支持这种写法。
我的程序中用到了好几个linux系统头文件,是向串口发指令之类的程序,程序中用到了互斥锁并创建了一个线程。
如果再用qt语言来写一遍的话我会挂掉的,所以没有办法,在网上找了半天,终于找到解决方法。
将.c文件编译为函数库的方式在qt下调用,这种方法貌似行得通,我就开始行动了。
下面的内容讲得比较多,比较全,比较适合初学者,是我在网上down的,给出了原网站的链接,最后给出了一个程序。
经过自己整理好归纳如下:需要说明的是:使用gcc可以将程序编译成动态库或者静态库的形式,它们在程序中的调用的方式也不尽相同,给出的程序中调用的是动态连接库。
编译成动态的还是静态的根据自己的需要进行。
如果原C程序编译的时候需要gcc的额外选项(如gcc -lpthread -o hello hello.c)等,建议采用动态的形式。
1.什么是静态连接库,什么是动态链接库静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib 中的指令都全部被直接包含在最终生成的EXE 文件中了。
但是若使用DLL,该DLL 不必被包含在最终EXE 文件中,EXE 文件执行时可以“动态”地引用和卸载这个与EXE 独立的DLL 文件。
静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。
在windows和linux上都是相同的,只不过文件的格式不同而已。
/winston/archive/2008/07/05/1236273.html2.gcc生成静态库和动态库第1步:编辑得到举例的程序--hello.h、hello.c和main.c;第2步:将hello.c编译成.o文件;无论静态库,还是动态库,都是由.o文件创建的。
c#调用c++dll接口及回调函数在合作开发时,C#时常需要调用C++DLL,当传递参数时时常遇到问题,尤其是传递和返回字符串是,现总结一下,分享给大家:VC++中主要字符串类型为:LPSTR,LPCSTR, LPCTSTR, string, CString, LPCWSTR, LPWSTR等但转为C#类型却不完全相同。
类型对照:BSTR --------- StringBuilderLPCTSTR --------- StringBuilderLPCWSTR --------- IntPtrhandle---------IntPtrhwnd-----------IntPtrchar *----------stringint * -----------ref intint &-----------ref intvoid *----------IntPtrunsigned char *-----ref byteStruct需要在C#里重新定义一个StructCallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str);注意在每个函数的前面加上public static extern +返回的数据类型,如果不加public ,函数默认为私有函数,调用就会出错。
在C#调用C++ DLL封装库时会遇到以下问题:首先是数据类型转换问题。
因为C#是.NET语言,利用的是.NET的基本数据类型,所以实际上是将C++的数据类型与.NET的基本数据类型进行对应。
因为调用的是__stdcall函数,所以使用了P/Invoke的调用方法。
其中的方法FunctionName 必须声明为静态外部函数,即加上extern static声明头。
我们可以看到,在调用的过程中,unsigned char变为了byte,unsigned short变为了ushort。
Process p = new Process();p.StartInfo.FileName = "sh";eShellExecute = false;p.StartInfo.RedirectStandardInput = true;p.StartInfo.RedirectStandardOutput = true;p.StartInfo.RedirectStandardError = true;p.StartInfo.CreateNoWindow = true;p.Start();p.StandardInput.WriteLine("ifconfig eth0 192.168.1.18 netmask 255.255.255.0 ");p.StandardInput.WriteLine("exit");string strResult = p.StandardOutput.ReadToEnd();TextBox1.Text = strResult;p.Close();C#调用C函数的方法:方法一:1.新建Visual C++类型的Win32项目C语言的函数定义如下:extern "C" __declspec(dllexport) int fnTestWin32(void);实现如下extern "C" __declspec(dllexport) int fnTestWin32(void){return 42;}工程属性页[常规]->[配置类型]选择[动态库.dll]会生成.lib和.dll文件。
用Dependency工具能看到fnTestWin32函数,因为使用了extern "C"2.C#工程中[DllImport("TestWin32.dll", EntryPoint = "fnTestWin32", CharSet = CharSet.Ansi)]private static extern int fnTestWin32();把Win32项目生成的dll拷贝到C#生成的exe文件,就可以调用了。
[动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。
动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。
函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。
DLL 还有助于共享数据和资源。
多个应用程序可同时访问内存中单个DLL 副本的内容。
动态链接库(Dynamic Link Library或者Dynamic-link library,缩写为DLL),是微软公司在微软视窗操作系统(即Windows操作系统)中实现共享函数库概念的一种方式。
这些库函数的扩展名是.DLL、.OCX(包含ActiveX控制的库)或者.DRV(旧式的系统驱动程序)。
动态链接库缩写为DLL,在电脑中可以更为容易地将更新应用于各个模块,而不会影响该程序的其他部分。
例如,您有一个大型网络游戏,如果把整个数百MB 甚至数GB的游戏的代码都放在一个应用程序里,日后的修改工作将会十分费时,而如果把不同功能的代码分别放在数个动态链接库(DLL)中,您无需重新生成或安装整个程序就可以应用更新。
]1.使用VC6.0 生成DLL新建项目“Win32 Dynamic-Link Library”,输入项目名称,确定后选择“A simple DLL project”点击“完成”。
以下为cpp文件自动生成的代码:#include "stdafx.h"BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){return TRUE;}编辑cpp文件:在#include "stdafx.h"的下一行加入extern "C" __declspec(dllexport) int fun(int a, int b);/*这是C格式导出函数;这种写法一般用在C++写的DLL中,指按C的规则导出这个函数,否则导出的函数会很怪; 加上extern "C" 表示按标准C格式导出函数.如果去掉仅兼容C++;其中int fun(int a, int b) 这部分代码是我们想用dll 实现的函数原型声明如果还想加入其他的可以继续加入extern "C" __declspec(dllexport) int fun1(int a, int b);*/DllMain 是DLL 的默认入口函数,类似于C语言的main函数,该例子无需修改此处,在DllMain 的后面加入:int fun(int a,int b){return a+b;}这就是我们想用DLL 实现的函数的定义,build 之后就会在debug 目录下生成我们想要的dll 文件2.调用DLL新建一个Win32 Console Application 工程,把刚才生成的dll 文件拷贝到工程的根目录下在stdafx.h 文件中加入:#include <windows.h>编辑cpp文件:#include "stdafx.h"typedef int (*PFUN)(int,int);void main(){HMODULE hModule = ::LoadLibrary("dlltest.dll");PFUN newfun = (PFUN)::GetProcAddress(hModule,"fun");int i = newfun(1,2);printf("The result is %d\n",i);::FreeLibrary(hModule);}然后,运行就可以看到结果了转VC6.0下调用Dll文件提供的函数接口和全局变量函数接口:首先把生成的Dll文件(如RegularDll.dll和RegularDll.lib)拷贝到当前工程所在文件夹,调用有两种方法:1)动态方法:使用LoadLibrary和GetProcAddress等函数,例typedef void (*lpFun)(void);HINSTANCE hDll;hDll = LoadLibrary("RegularDll.dll");if (NULL==hDll) {MessageBox("Dll load failed!");}lpFun pShowDlg = (lpFun)GetProcAddress(hDll,"ShowDlg");if (NULL == pShowDlg) {MessageBox("Load function \"ShowDlg\" failed!");}pShowDlg();*/2)静态声明方法:创建Dll的工程中,函数声明和定义时用_stdcall 修饰,例void _stdcall ShowDlg(void){...}在调用dll的工程的文件中,在文件头部声明库和函数,如下例#pragma comment(lib,"RegularDll.lib")void _stdcall ShowDlg(void);调用时直接ShowDlg()就可以了。
c语言生成库文件过程C语言是一种高级编程语言,被广泛用于系统级编程和嵌入式系统开发。
为了提高代码的复用性和模块化程度,C语言提供了生成库文件的机制。
本文将详细介绍C语言生成库文件的过程,以及相关的概念和步骤。
一、库文件的概念库文件是一种二进制文件,包含一组函数、变量或者数据结构的实现。
它将一些常用的代码封装成一个独立的单元,供其他程序调用和使用。
库文件可以被静态链接到程序中,也可以被动态链接到程序中。
1. 静态库(Static Library):静态库是将库文件的内容完全复制到程序中,程序在编译时需要将所有被引用的库文件的代码复制到最终生成的可执行文件中。
具体来说,静态库以归档(Archive)的形式存在,包含了一组目标文件(Object File)的集合。
静态库的文件名通常以“.a”(在GNU 编译器中)或“.lib”(在Windows中)结尾。
2. 动态库(Dynamic Library):动态库是在程序运行时被动态加载到内存中的库文件,程序在编译时只需要引用库函数的签名,无需复制库文件中的代码。
不同的程序可以共享同一个动态库的实例,有效减小可执行文件的体积。
动态库的文件名通常以“.so”(在Unix/Linux中)或“.dll”(在Windows中)结尾。
在使用库文件时,程序需要链接器(Linker)的支持,将库文件的代码和程序的代码进行整合,生成最终的可执行文件。
二、生成静态库的过程下面将介绍生成静态库的过程,以GNU编译器为例。
1. 编写源代码首先,需要编写一组实现某些功能的源代码文件。
这些源代码文件可以包含函数的定义、变量的声明和实现,以及相关的头文件。
2. 编译为目标文件使用编译器将源代码文件编译为目标文件(Object File)。
目标文件是二进制文件,包含了源代码文件的机器代码表示和一些符号表信息。
使用gcc 命令可以进行编译,例如:gcc -c file1.c file2.c这将生成`file1.o`和`file2.o`两个目标文件。
C语言如何生成库文件?
1.现将二个函数Sub1()及Sub2()建立成一个函数库文件取名MyLib.Lib。
两个函数的类型及形参如下:
Void Sub1(Void);Float Sub2(Int i,Float x)将它们分别建立一个文件,取名为Sl.c 及S2.c,再用命令Tcc对它们分别编译后产生两个目标文件S1.obj及S2.obj,最后使用Tlib命令建立函数库文件MyLib.Lib,并建立相应的列表文件(列表文件主要用来检查主函数库情况),命令格式如下:Tcc S1. c S2. c Tlib MyLib +S1 +S2,MyLib.Lst 将产生的Mylib.Lib函数库文件拷贝到标准库目录下C:\TC\Lib.
2.建立其首标文件(假设取名为myfunc.h)内容如下:extern void sub1(void);
extern float sub2(int,float);
将此文件拷贝到目录下c:\tc\include.
3.在用户的程序中按下列方式直接使用即可
#include<myfunc.h>main(){… 调用Sub1();Sub2();… } 4.在Turboc下用编译命令Tcc对用户程序进行编译及链接。
设其用户程序文件名为My.c,使用命令格式:Tcc -I C:\TC\include -L C:\TC\Lib My. c Mylib.lib 执行完后就会产生一个My.exe可执行文件,其中-I后面指出首标文件的目录,而-L后面指出函数库的子目录,最后两个分别是源程序文件及函数库文件。
关于Tcc和Tlib的详细用法在系统提示符下键入C:\TC\TCC和 C :\TC\Tlib可得到帮助。
网上找的,瞒详细的,希望对你有帮助,平时学习没遇到相关的要求。
c 语言接口与实现一、概述C语言是一种广泛使用的编程语言,其接口和实现对于程序员来说非常重要。
C语言的接口是指程序与外部组件进行交互的方式,而实现则是指如何将代码转换为可执行文件。
本文将介绍C语言接口与实现的相关知识。
二、C语言接口1. 函数接口函数是C语言中最基本的接口形式之一。
函数接口由函数名称、参数列表和返回值组成。
在调用函数时,需要提供正确的参数列表,并根据需要处理函数返回值。
2. 文件接口文件接口允许程序读取和写入文件。
在C语言中,文件被视为流(stream),可以使用标准I/O库中的函数来操作它们。
3. 网络接口网络接口允许程序通过网络进行通信。
在C语言中,可以使用套接字(socket)API来创建网络连接并发送和接收数据。
4. GUI 接口GUI(图形用户界面)接口允许程序创建窗口、按钮、文本框等图形元素,并响应用户输入事件。
在C语言中,可以使用第三方库如GTK+或Qt来创建GUI应用程序。
三、 C语言实现1. 编译器编译器是将源代码转换为可执行文件的工具。
C语言编译器通常包括预处理器、编译器和链接器三个部分。
预处理器负责处理源代码中的预处理指令,编译器将C语言源代码转换为汇编语言,链接器将多个目标文件合并为一个可执行文件。
2. 运行时库运行时库是一个动态链接库,包含了C语言程序运行时需要的函数和变量。
在程序运行时,操作系统会加载运行时库,并将其链接到程序中。
3. 操作系统操作系统是一个底层软件层,负责管理计算机硬件资源并提供各种服务。
C语言程序通常需要依赖操作系统提供的服务来完成一些任务,如文件读写、网络通信等。
四、 C语言接口与实现的关系C语言接口和实现是紧密相关的。
接口定义了如何与外部组件进行交互,实现则决定了代码如何被转换为可执行文件。
在设计C语言程序时,需要考虑接口和实现之间的关系,并确保它们之间的协调一致性。
五、总结本文介绍了C语言接口与实现的相关知识。
C语言接口包括函数接口、文件接口、网络接口和GUI 接口等形式;而实现则包括编译器、运行时库和操作系统等组成部分。
由C++生成C接口函数库的方法
1、在Visual C++中创建动态链接库工程。
2、函数声明方式为:__declspec(dllexport) void function();
加入__declspec(dllexport)的作用是提示编译器myfunction()函数为dll文件的输出函数。
同样道理,定义dll输出变量也应在声明前加__declspec(dllexport)。
3、欲使输出函数按照C语言标准编译需要加入extern “C”.如下:
extern “C”{
__declspec(dllexport) void function1();
__declspec(dllexport) void function2();
__declspec(dllexport) void function3();
__declspec(dllexport) void function4();
}
注意”C”这里的C必须是大写的。
这里详细说明extern “C”{ }的作用。
首先,需要了解的是C++和C函数编译方式的差异,由于C++里面支持函数的重载,因此编译出来的.obj或者库文件里面,函数名会被加上和参数有关的签名,用来区分同样函数名参数不同的函数。
然而C语言不支持重载,所以函数名里面没有这样的签名。
这样,当C语言的程序调用C++写成的库的时候,就会找不到函数。
比如,一个函数叫void foo(int bar)之类的,可能会在c++编译成叫foo_i之类的名字,而在c语言里面就会编译成foo,这样c语言的程序去找foo就会找不到,这样连接的时候会出错。
为了解决这个问题,引入了extrn "c"{},在这个的作用域之内,c++的函数名不会加上参数签名,和c语言的标准保持统一,就兼容c语言的程序了。
4、接口函数不能存在C++支持而C不支持的形参。
如std::string等。
生成的库可以像C语言链接库一样被使用。
可以采用以下模板
//mylib.h
#define EXPORT_API __declspec(dllexport)
extern “C”{
EXPORT_API void function1();
EXPORT_API void function2();
}
//mylib.cpp
#include “mylib.h”
EXPORT_API void function1()
{
}
EXPORT_API void function2()
{
}。