Delphi10.3.X跨平台调用动态链接库

2019-05-20 跨平台调用动态库

Windows平台

Windwos平台使用 静态加载方式加载dll

  1. C++代码

我使用的我是使用vs2019

#include 
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;
}
  1. Delphi代码
// 声明调用
function Tadd(a, b: Integer): Integer; stdcall; external 'Cpp_Windows_Dll_Demo' name 'stdadd';

Writeln(Tadd(10, 20));

  1. 结果
    Delphi10.3.X跨平台调用动态链接库_第1张图片

网上有朋友说stdadd函数名称会变,但是我这里没有啊(可以使用Dll Export Viewer工具查看一下编译后的dll文件的函数名)
Delphi10.3.X跨平台调用动态链接库_第2张图片

Linux

Linux平台目前测试只能使用动态加载方式来使用

  1. C++ 代码,文件后缀名为.cpp
#include 
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
    在这里插入图片描述
  1. 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;

  1. 执行结果
    Delphi10.3.X跨平台调用动态链接库_第3张图片

完整的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.

你可能感兴趣的:(Delphi,Linux,Windows,Delphi,Delphi跨平台)