从动态库

时间:2017-04-13 15:04:34

标签: c++ shared-libraries lazarus

我刚买了一个代表设备SDK的共享库(.so共享对象)。 卖家没有向我发送用于C / C ++开发的头文件.h文件。他们使用interface(java类)和Pascal全局函数向我发送了Pascal和Java示例,这些函数引用了stdcalls也引用了这个外部.so文件。

他们向我发送了关于如何在Pascal和Java上使用.so共享对象的示例和演示。 他们还向我发送了一份详细说明.so文件中所有函数调用(参数类型等)的文档。我在.so文件中看到了确切的函数符号。

我的问题是,如何创建一个C ++标头,我可以将它用作C ++中的类对象。

我使用dlopen,dlsym和dlclose在我的软件上直接使用了这个.so,但我觉得它很脏。因此,我想为此创建一个类似java接口的类,这样我就可以创建一个更干净的代码,并且可以在线程上单独运行而不会像现在一样冻结我的GUI。

他们为我提供的Pascal(Lazarus)函数定义:

  THREAD_READ1  = class(TThread)
    fEvent:PRTLEvent;
    procedure Execute; override;
    constructor Create;
    destructor Destroy; override;
  end;

{ Functions headers }
function SDK_Initialize: integer; stdcall; external 'sdk.so';
function SDK_Finalize: integer; stdcall; external 'sdk.so';
function SDK_DigitalREAD(pTemplate: Pointer): integer; stdcall; external 'sdk.so';
function SDK_READBMP(var iRetorno, iSize: Integer): Pointer; stdcall; external 'sdk.so';
function SDK_READ(pTemplate: Pointer; var sTemplate: integer; pImage: Pointer; var sImage:integer; intWHITE: integer; intIMG: integer): integer; stdcall; external 'sdk.so';
function SDK_Cancel: integer; stdcall; external 'sdk.so';
function SDK_Compare(pSample1, pSample2: Pointer): integer; stdcall; external 'sdk.so';

function SDK_Version: PAnsiChar; stdcall; external 'sdk.so';
function SDK_Return(intReturn: integer): PAnsiChar; stdcall; external 'sdk.so';

我需要知道如何将这些函数调用移植并包装到C ++类中,并将一些函数运行到不同的Thread中,例如:

    Class Device : public QObject {
Q_OBJECT
private:
QThread thread1;
QThread *thread2;
...
public:
SDK functions here
...
};

我不知道如何在上面的代码中构造函数头。而且我也不知道如何使其线程安全如下: 我必须在线程上调用SDK_READ以将设备置于读状态,而不是让我的GUI冻结等待设备响应。 我还必须调用SDK_Cancel取消读取状态并完成运行任何SDK_READ函数的线程

1 个答案:

答案 0 :(得分:0)

自Lazarus'以来,SDK *函数可以1:1映射到GCC。编译器,Freepascal,通常与链接级别的gcc兼容。所有类型都是原始类型,因此它只需要基本的语法转换,并且需要使用任何stdcall调用约定宏。 VAR参数添加一个额外的*间接。

注意"整数",通常是int32,但严格来说这取决于编译器模式。 (objfpc和delphi = int32,默认模式和TP = int16)。这是TThread类派生的唯一好处,它确保这是一个Object Pascal模式。

然而,Thread_read1_类是本机对象(OOP)Pascal,并且不能与外部代码(甚至是一个明显不同的FreePascal或Delphi版本)进行交互,并且需要像普通C接口或不同C ++编译器的任何C ++类一样进行包装。将。 (例如,比较gcc在过去多次改变C ++类的修改时)。

理论上你可以尝试入侵它,但这是不可取的,特别是因为TThread也会创建大量的TLS上下文。标题的这一部分似乎不能从外部语言或版本中重复使用

花费5000欧元来使用Delphi作为转换器来转换像Rudy这样的10个函数可能会有点矫枉过正。

---私人邮件中的更多细节后的回复

整个事情非常不清楚,标题并没有提供太多信息。在一封私人邮件中,海报解释了这种情况,似乎这些功能可以正常工作,但是从线程中使用时却不行。

可能在未由FPC初始化的线程中运行FPC代码 运行时会导致问题。

我之前在评论中发布的网址( http://wiki.freepascal.org/Multithreaded_Application_Tutorial#External_threads )描述由嵌入CEF(Chrome浏览器)的人创建的一些原因 在Lazarus应用程序中。 CEF也是内部线程化的,并在其线程中调用pascal回调。

基本上有两个可能的原因:

  1. FPC中的线程RTL尚未初始化(通过创建虚拟线程完成)

  2. 如果Pascal代码使用动态内存等FPC运行时组件 必须使用TLS变量的管理或标准文件描述符 调用一个函数来做到这一点。 (" ExternalThread"链接中的位)。

  3. 如果SDK将这些部分包装在SDK中,它可能是一块蛋糕 为了你。访问可能未导出的(或可能是部分的) 甚至没有链接在一起。静态链接到.so的RTL符号将是 但是,非常努力,所以与SDK供应商交谈似乎是唯一的理智 大道恕我直言,或放弃线程愿望,例如与工人一起工作 连接使用管道控制的SDK的应用程序。

    SDK api有点幼稚,如果已经迭代,则不会发出声音,并且不会为在一个应用程序中可能是多语言运行时的情况做好准备。