欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Windows及Linux下动态库的编译与调用示例

程序员文章站 2022-06-04 13:02:45
...

Windows 下:

动态库编写

//.h file

//extern "C" 保证该函数按C语言的方式编译
#ifdef __cplusplus
extern "C" {
#endif

#ifndef DRILLING_TRACE_EVALUATE_H
#define DRILLING_TRACE_EVALUATE_H

/*
1 因为 DLL_EXPORTS 在本头文件对应的 .c 文件里进行了宏定义(见下 .c file),所以,有:
    (1)如果是进行动态库编译,则将_declspec(dllexport) 简化为 DLL_API。
    (2)如果是动态库调用(此时,实现文档 .c 文件已经为机器码),对于主调程序 DLL_EXPORTS 没有进行宏定义,
        故将_declspec(dllimport) 简化为 DLL_API。
2 为了动态库的通用性,这里还可以加上平台是否是 win32 的检验(本例没有做)。
*/
#ifndef DLL_EXPORTS
#define DLL_API _declspec(dllexport)
#else 
#define DLL_API _declspec(dllimport)
#endif // !DLL_API

// __stdcall 是c/c++的Windows扩展,目的:指定接口为标准调用方式,使得其他语言可以调用接口。
DLL_API double __stdcall epsilon(double k, double c_k, double dl);

#endif // DRILLING_TRACE_EVALUATE_H

#ifdef __cplusplus
}
#endif
//.c file

//vs 里的环境变量设置等操作的头文件,其他 IDE 中不用它
#include "stdafx.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <math.h>
#include "drilling_trace_evaluate.h"

#define DLL_EXPORTS 
#define PI 3.14159265358979323846

DLL_API double __stdcall epsilon(double k, double c_k, double dl)
{
	double p = -1.0;
	if (0.0 == c_k){return p; }
	p = (k * dl / c_k)*(PI / 180.0);
	return p;
}

#ifdef __cplusplus
}
#endif

调用动态库:

/*
1 动态库编译后会得到很多文件,但是对于调用只需要3个文件:
    drilling_trace_evaluate.h
    drilling_trace_evaluate.lib
    drilling_trace_evaluate.dll
2 需要将上述3个文件置于调用程序的工作目录下
*/
    

//每个语言调用的方式可能不一样,因为它们的 API 不同

/*
c和c++ 调用动态库的方式:在实际调用动态库的文件开头加上下列2句后,
便可以像普通函数一样调用动态库函数了
*/
#include "drilling_trace_evaluate.h"
#pragma comment(lib, "drilling_trace_evaluate.lib")

//python 调用动态库
from ctypes import *
drilling_trace_evaluate = CDLL("drilling_trace_evaluate.dll")
//设置 c 函数的返回值为 double类型(因为 Python 默认 c 函数的返回值为 int 型)
drilling_trace_evaluate.epsilon.restype = c_double
print(drilling_trace_evaluate.epsilon(c_double(10.2),c_double(22.7),c_double(11.11)))

Linux 下:

/*
1 linux 下,编写动态库不需要 _declspec(export),_declspec(import),__stdcall 这些扩展修饰语法
2 正常编写完 .h 和 .c 后,将 .h 文件放到 /usr/include 目录下,
    然后通过下列命令得到 . so 文件,将其放于工作目录之下便可以调用:
        gcc drilling_trace_evaluate.c –fPIC –shared –o drilling_trace_evaluate.so

        –fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通
                过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
        –shared:指明编译成动态库。
*/


//python 调用:
from ctypes import *
drilling_trace_evaluate = CDLL("./drilling_trace_evaluate.so")
//设置 c 函数的返回值为 double类型(因为 Python 默认 c 函数的返回值为 int 型)
drilling_trace_evaluate.epsilon.restype = c_double
print(drilling_trace_evaluate.epsilon(c_double(10.2),c_double(22.7),c_double(11.11)))

 

相关标签: 动态库