2019-05-20 跨平台调用动态库
Windows平台
Windwos平台使用 静态加载方式加载dll
- C++代码
我使用的我是使用vs2019
#include <iostream>
using namespace std;
extern "C" int __declspec(dllexport) __stdcall stdadd(int x, int y);
int stdadd(int x, int y)
{
cout << "我是C++里面的输出语句" << endl;
return x + y;
}
- Delphi代码
// 声明调用
function Tadd(a, b: Integer): Integer; stdcall; external 'Cpp_Windows_Dll_Demo' name 'stdadd';
Writeln(Tadd(10, 20));
- 结果
网上有朋友说stdadd函数名称会变,但是我这里没有啊(可以使用Dll Export Viewer工具查看一下编译后的dll文件的函数名)
Linux
Linux平台目前测试只能使用动态加载方式来使用
- C++ 代码,文件后缀名为.cpp
#include <iostream>
using namespace std;
//extern "C" int __declspec(dllexport) __stdcall stdadd(int x, int y);
int stdadd(int x, int y)
{
cout << "我是C++里面的输出语句" << endl;
return x + y;
}
编译:
g++ test_so.cpp -fPIC -shared -o libnum.so
查看so文件的函数
# 下面命令任选一条
nm -D libnum.so | grep stdadd
objdump -tT libnum.so | grep stdadd
函数名变了
如果是C语言的话就不会变
- 把cpp文件改为c后缀名;
- 执行:gcc test_so.cpp -fPIC -shared -o libnum.so 编译so文件
- 查看函数,我这里把stdadd函数改为了add
- Delphi代码
// 定义一个函数指针
var
MyFun: function(a, b: Integer): Integer;
if not FileExists('/home/parallels/桌面/Tools/Test/so/libnum.so') then
begin
Writeln('libnum.so文件不存在');
end
else
begin
try
Hand := LoadLibrary('/home/parallels/桌面/Tools/Test/so/libnum.so');
if Hand <> 0 then
begin
Writeln('so文件加载成功');
MyFun := GetProcAddress(Hand, '_Z6stdaddii');
Writeln(MyFun(30, 10));
end;
finally
FreeLibrary(Hand);
end;
end;
- 执行结果
完整的Delphi跨平台代码
program Demo01_Call_CppDll;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
{$IFDEF LINUX}
var
MyFun: function(a, b: Integer): Integer;
{$ELSE}
function Tadd(a, b: Integer): Integer; stdcall; external 'Cpp_Windows_Dll_Demo' name 'stdadd';
{$ENDIF}
var
Hand: Cardinal;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
Writeln('Call so');
{$IFDEF LINUX}
if not FileExists('/home/parallels/桌面/Tools/Test/so/libnum.so') then
begin
Writeln('libnum.so文件不存在');
end
else
begin
try
Hand := LoadLibrary('/home/parallels/桌面/Tools/Test/so/libnum.so');
if Hand <> 0 then
begin
Writeln('so文件加载成功');
MyFun := GetProcAddress(Hand, '_Z6stdaddii');
Writeln(MyFun(30, 10));
end;
finally
FreeLibrary(Hand);
end;
end;
{$ELSE}
Writeln(Tadd(10, 20));
{$ENDIF}
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.