g++ 生成C++ .so库文件,并调用示例

摘要:
handle){cout˂˂dlerror()˂˂endl;return-1;}typedefint(*add_t)(inta,intb);add_tadd=(add_t)dlsym(handle,"TestAdd");if(!

Tags: g++ C++ so library

在Linux系统下用g++命令编译C++程序.也可以生成so,a链接库

示例一 编译时链接so库

Test.h 文件内容

g++ 生成C++ .so库文件,并调用示例第1张

Main.cpp文件内容

g++ 生成C++ .so库文件,并调用示例第2张

命令执行过程

g++ 生成C++ .so库文件,并调用示例第3张

//生成so文件

g++ -shared -fPIC -o libTestLib.so Test.h

//编译Main.cpp并链接so.生成可执行文件Main

g++ Main.cpp -o Main -L.

//执行可执行文件Main

./Main

使用Makefile

g++ 生成C++ .so库文件,并调用示例第4张

Makefile解读

Makefile的基本规则是

生成目标 : 依赖目标

<TAB>命令

Makefile会首先检查生成目标依赖目标,若所有依赖目标准备好,则执行下一行以<TAB>(制表符)开头的命令,来产生生成目标.

一般来说一个Makefile只有一个最终目标(一般是Makefile定义的第一个).而这个目标可以依赖其他目标,Makefile会自动检查依赖,并且按依赖关系逐个生成

上面Main目标依赖LibTest.so Main.cpp,其中Main.cpp是源文件,不需要生成,而LibTest.so是一个目标,因此Makefile会找到LibTest.so的生成规则,并首先生成LibTest.so再生成最终目标Main

LibTest.so的生成又依赖于Test.h文件,其中Test.h是源文件,所以可以直接利用下面的<Tab>后的命令生成LibTest.so.因此Makefile首先执行的是g++ -shared -fPIC -o LibTest.so Test.h

在生成LibTest.so后,最终目标Main的所有依赖文件已经准备好,则Makefile执行

g++ Main.cpp -o Main -L.

来生成最终目标Main文件

伪目标

Mainfile中的clean也是一个目标,但是并不依赖于任何文件,这种目标称为伪目标,而且应该用

.PHONY: clean

来声明该伪目标.

Makefile的执行:

对于Makefile的最终目标(一般为第一个),可以直接在命令行执行make命令,由Makefile自动识别来执行

也可以使用

make 目标名

来执行指定目标,而对于伪目标clean,则必须使用 make clean的方式显示执行:

make clean

参考

http://blog.csdn.net/haoel/article/details/2887

注意:

-shared 是指生成动态链接库,详细查Google

http://blog.sina.com.cn/s/blog_54f82cc201011op1.html-fPIC 是指编译代码为可共享,参考:

-o 后面为输出文件名称

-L. 是指的在以下位置查找链接库,其中L后面的(.)是指的是当前目录

示例二 代码动态加载库

若要动态加载.so库则需要使用dlopen 等函数

目录结构

g++ 生成C++ .so库文件,并调用示例第5张

Test.h内容

extern "C" {

int TestAdd(int x, int y);

}

Test.cpp内容

#include "Test.h"

extern "C" int TestAdd(int x, int y)

{

return x + y;

}

Main.cpp内容

#include <dlfcn.h>

#include <iostream>

using namespace std;

int main(int argc, char *argv[])

{

void *handle = dlopen("./Test.so", RTLD_LAZY);

if (!handle)

{

cout << dlerror() << endl;

return -1;

}

typedef int (*add_t)(int a, int b);

add_t add = (add_t) dlsym(handle, "TestAdd");

if (!add)

{

cout << dlerror() << endl;

dlclose(handle);

return -1;

}

int a = add(3,5);

cout << "a = " << a << endl;

dlclose(handle);

return 0;

}

Makefile内容:

Main: libTest.so Main.cpp

g++ -ldl -o Main Main.cpp

libTest.so: ./Sources/*.cpp

g++ -shared -fPIC -o libTest.so ./Sources/*.cpp -I ./Headers/

.PHONY: clean

clean:

-rm -f Main

-rm -f libTest.so

注意:

1.

不管什么库文件,你都既要在包含.h文件(不然编译通不过:有未声明的函数),也要在gcc选项里面指定.so文件的位置(不然链接通不过:未知的符号) 比如 gcc -I include_path -L lib_path -lyourlib include_path改成你头文件的目录 lib_path改成你动态库文件的目录 -lyourlib 改成l加上你要引用的库文件名字 比如libpthread.so就改成-lpthread

http://blog.chinaunix.net/uid-21273878-id-4148042.html

示例三 Linux下Eclipse 中调用so文件

首先在Linux下安装Eclipse,确保jdk环境都配置ok

创建Eclipse工程,创建java代码源文件

TestLib.java

public class TestLib {

static{

System.loadLibrary("Test");

}

public static native int TestAdd(int a, int b);

public static void main(String args[])

{

System.out.println(TestAdd(1, 2));

}

}

在TestLib.java文件目录下,使用javac命令生成TestLib.class文件

javac TestLib.java

在bin目录下,找到生成的TestLib.class 文件(若没有该文件,则在TestLib.java相同目录下找,并复制到bin目录下.

在bin目录下,执行以下命令生成C++工程使用的TestLib.h文件

javah -classpath . -jni TestLib

生成的TestLib.h

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class TestLib */

#ifndef _Included_TestLib

#define _Included_TestLib

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: TestLib

* Method: TestAdd

* Signature: (II)I

*/

JNIEXPORT jint JNICALL Java_TestLib_TestAdd

(JNIEnv *, jclass, jint, jint);

#ifdef __cplusplus

}

#endif

#endif

创建C++代码Test.cpp,实现TestLib.h中定义的各接口:

Test.cpp

include "TestLib.h"

JNIEXPORT jint JNICALL Java_TestLib_TestAdd

(JNIEnv *env, jclass cls, jint a, jint b)

{

return a + b;

}

编写Makefile

Makefile 内容

libTest.so: ./Sources/*.cpp

g++ -shared -fPIC -o libTest.so ./Sources/*.cpp -I ./Headers/

-I /usr/lib/jvm/java-1.7.0-openjdk.x86_64/include

-I /usr/lib/jvm/java-1.7.0-openjdk.x86_64/include/linux

命令行执行 make libTest.so

生成libTest.so文件,将so文件拖到Eclipse项目中.运行Eclipse项目.

正确调用libTest.so中定义的接口

注意:

生成的TestLib.h包含了jni.h文件,而且需要jni_md.h文件.所以在g++命令时,需要用 -I 参数指定这两个头文件的路径

免责声明:文章转载自《g++ 生成C++ .so库文件,并调用示例》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[转]LINQ查询总结python运维常用相关模块下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

qt creator编译问题之 can not find -lQtGui

今天尝试在(qtcreator 4.7.0 + Qt 4.8.6)下编译,遇到找不到库文件问题,先开始想到的是环境配置问题 检查下来也没有线索, 又想是不是没有链接路径,参考网上,试了两个个命令 ld -lQtNetwork --verbose  locate libQtNetwork ld -lQtNetwork --verbose  locat...

android编译系统的makefile文件Android.mk写法

(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件,即要编译的文件。由于一般情况下 Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式: LOCAL_PATH:=$(call my-dir) 上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。 (2)Android.mk中可以定义多个编...

从 C++ 到 Qt(命令行编译)good

从 C++ 到 Qt 转载自:http://hi.baidu.com/cyclone/blog/item/8f8f08fa52d22f8758ee9006.html Qt 是 C++ 的库,Qt在ansi C++ 的基础上进行了一点扩展。 但国内似乎比较浮躁,学Qt的很多连基本的C++如何编译似乎都不太清楚。本文舍弃IDE或qmake、cmake等工具的...

Linux下安装Nginx并实现socket代理

nginx可以使用各平台的默认包来安装,本文是介绍使用源码编译安装,包括具体的编译参数信息。 正式开始前,编译环境gcc g++ 开发库之类的需要提前装好,这里默认你已经装好。 ububtu平台编译环境可以使用以下指令 1 2 apt-get install build-essential apt-get install libtool cen...

移植QT5.6到嵌入式开发板(史上最详细的QT移植教程)

目前网上的大多数 QT 移植教程还都停留在 qt4.8 版本,或者还有更老的 Qtopia ,但是目前 Qt 已经发展到最新的 5.7 版本了,我个人也已经使用了很长一段时间的 qt5.6 for windows ,本文就来介绍一下QT在嵌入式环境的搭建。   移植以到 JZ2440 为例,使用韦老大提供的 ubuntu9.10 虚拟机作为移植环境。当然,...

性能分析工具gprof介绍

转载自: http://blog.chinaunix.net/uid-25194149-id-3215487.html 还有另外一个介绍的博客: http://blog.csdn.net/cbbbc/article/details/44629171 Ver:1.0目录1.    GPROF介绍    42.    使用步骤    43.    使用举例  ...