windows和ubuntu下显式调用dll库文件的异同

windows和ubuntu下显式调用dll库文件的异同

除了将dll库文件作为一部分参与主程序编译之外,显式的调用库文件也是一种灵活的使用方式。
调用dll库文件依赖于系统,所以不同的系统下是不同的。
像c++这种静态编译程序就要注意这样的不同,而python这种动态程序由于解释器已经做了处理则可以忽略系统的差异。本文就讨论一下这些内容:

1. c++程序显式调用库文件

c++程序显式的调用库文件,就是在程序中显式的打开库文件,并定位和使用其中的函数。

1.1 windows下的调用

下面的c++源程序是典型的windows系统下dll显式调用程序:

#include <iostream>
#include <stdio.h>

#include <windows.h>
using namespace std;  

typedef double (*WinrateFunc)(int, int,int,int, int, int, int, int, int);
typedef void (*Wrlibinit)();


/* main.cpp */  
int main(){
		
	//动态加载Dlltest.dll文件
	HINSTANCE hDll;
	hDll= LoadLibrary(TEXT("libwinrate.so"));
	
	//测试是否能够正确输出
	//printf("%s\n","absededeedd");
	//cout<<"absededeedd"<<endl;
	

	if (hDll != NULL)
    {
		
		WinrateFunc getwinrate = (WinrateFunc)GetProcAddress(hDll, "get_winrate");
		Wrlibinit getwrinit = (Wrlibinit)GetProcAddress(hDll, "compinit");
		if (getwinrate != NULL) {
			getwrinit();
			double wr=getwinrate(2,5,24,37,15,18,45,51,34);
			cout<<"wr="<<wr<<" true val="<<0.2631<<endl;

			wr=getwinrate(2,0,10,52,0,0,0,0,0);
			cout<<"wr="<<wr<<" true val="<<0.5672<<endl;

			wr=getwinrate(2,4,21,39,29,17,26,1,0);
			cout<<"wr="<<wr<<" true val="<<0.4030<<endl;

			wr=getwinrate(3,0,29,35,0,0,0,0,0);
			cout<<"wr="<<wr<<" true val="<<0.3575<<endl;

		}
			
	
		//卸载Dlltest.dll文件;
		FreeLibrary(hDll);
	
	}
    return 0;  
}  

其中:

(1)#include <windows.h>是调用dll的系统头文件依赖;

(2)hDll= LoadLibrary(TEXT("libwinrate.so"));则是显式的打开库文件;

(3)typedef void (*Wrlibinit)(); 则是声明库文件中函数及其参数的类型;

(4)Wrlibinit getwrinit = (Wrlibinit)GetProcAddress(hDll, "compinit");则是定位获取库文件中的函数;

(5)getwrinit();则是使用库文件中的函数。

(6)FreeLibrary(hDll);则是使用完dll后显式的关闭库文件。

1.2 ubuntu下的调用

linux系统如ubuntu下由于依赖的系统库的不同,所以有所差别,其典型程序如下:

#include <iostream>
#include <stdio.h>
//windows
//#include <windows.h>
//linux
#include <dlfcn.h>


using namespace std;  

typedef double (*WinrateFunc)(int, int,int,int, int, int, int, int, int);
typedef void (*Wrlibinit)();


/* main.cpp */  
int main(){
		
	//动态加载Dlltest.dll文件
	void* hDll;
	hDll= dlopen("./libwinrate.so",RTLD_LAZY);
	
	if (hDll != NULL)
    {
		
		printf("%s\n","dll loaded!!");

		WinrateFunc getwinrate = (WinrateFunc)dlsym(hDll, "get_winrate");
		Wrlibinit getwrinit = (Wrlibinit)dlsym(hDll, "compinit");
		if (getwinrate != NULL) {
			getwrinit();
			double wr=getwinrate(2,5,24,37,15,18,45,51,34);
			cout<<"wr="<<wr<<" true val="<<0.2631<<endl;

			wr=getwinrate(2,0,10,52,0,0,0,0,0);
			cout<<"wr="<<wr<<" true val="<<0.5672<<endl;

			wr=getwinrate(2,4,21,39,29,17,26,1,0);
			cout<<"wr="<<wr<<" true val="<<0.4030<<endl;

			wr=getwinrate(3,0,29,35,0,0,0,0,0);
			cout<<"wr="<<wr<<" true val="<<0.3575<<endl;

		}
			
	
		//卸载Dlltest.dll文件;
		dlclose(hDll);
	
	}
    return 0;  
}  

其中:

(1)#include <dlfcn.h>是调用dll的系统头文件依赖;

(2)hDll= dlopen("./libwinrate.so",RTLD_LAZY);则是显式的打开库文件;

(3)typedef void (*Wrlibinit)(); 则是声明库文件中函数及其参数的类型;

(4)Wrlibinit getwrinit = (Wrlibinit)dlsym(hDll, "compinit");则是定位获取库文件中的函数;

(5)getwrinit();则是使用库文件中的函数。

(6)dlclose(hDll);则是使用完dll后显式的关闭库文件。

1.3 两个系统下的比较

两个系统下dll调用的差异,如下表所示:

差异项windowsubuntu
头文件依赖windows.hdlfcn.h
库打开LoadLibrarydlopen
函数获取GetProcAddressdlsym
库关闭FreeLibrarydlclose
------------
相同项windowsubuntu
函数类型声明使用typedef定义同左
库中函数使用直接使用获取的函数同左
------------

2. python程序显式调用库文件

而python由于其解释器本身就是跨平台的所以在不同的系统下,其函数的调用是相同的,而且接口更为简单。
其典型程序如下:

#!/usr/bin/env python3
#_*_coding: utf-8 _*_

import sys
import json
import struct
import socket

from ctypes import *  #用import *的方式可以把c_float,c_double等类型载入进来,而不用再带一个ctypes.
loadlib = cdll.LoadLibrary

lib = loadlib("./libwinrate.so")
lib.compinit()
getwinrate=lib.get_winrate
getwinrate.argtypes = [c_int,c_int,c_int,c_int,c_int,c_int,c_int,c_int,c_int]
getwinrate.restype= c_double

wr=getwinrate(2,5,24,37,15,18,45,51,34)
print("wr=",wr,' true val=',0.2631313131313131)

wr=getwinrate(2,0,10,52,0,0,0,0,0)
print("wr=",wr,' true val=',0.5672969999999999)

wr=getwinrate(2,4,21,39,29,17,26,1,0)
print("wr=",wr,' true val=',0.40303030303030307)

wr=getwinrate(3,0,29,35,0,0,0,0,0)
print("wr=",wr,' true val=',0.3575082176846212)

其中:

(1)lib = loadlib("./libwinrate.so") 是调用dll;

(2) 库中的函数可以直接使用,比如lib.compinit()

(3) 库中的函数可以赋给一个对象后使用,比如getwinrate=lib.get_winrate

(4) 最好声明一下函数的输入输出类型,比如getwinrate.argtypesgetwinrate.restype

3. 库文件编译的差异

对于自己用c++编写的库文件,也是需要在不同的系统下编译的,因此对于程序本身可能依赖的部分头文件差异外最大差异是编译命令的差异:

windows 典型为:

g++ -g -std=c++11  -shared -Wall -o libwinrate.so winrate.cpp pokerlib.cpp  mtrand.cpp  -O3

ubuntu下典型为:

g++ -g -std=c++11  -shared -fPIC -o libwinrate.so winrate.cpp pokerlib.cpp  mtrand.cpp  -O3  -fno-stack-protector

4. 小结

本文简单介绍了不同系统下程序显式调用dll库文件的差异,为不同系统下的程序迁移提供帮助。

参考:

  1. 【qt/c++调用dll的方法实践】
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值