1

我正在尝试为ØMQ C library编写 ABL 绑定,但是我的zmq_init函数绑定的过程编辑器崩溃了。我为 zmq_version 编写了一个绑定没有问题,所以我认为这不是 .dll 文件问题。无论如何,C 函数原型如下所示:

void *zmq_init (int io_threads);

我写的ABL代码如下:

PROCEDURE zmq_init EXTERNAL "libzmq.dll" CDECL:
  DEFINE INPUT  PARAMETER num_threads AS LONG.
  DEFINE RETURN PARAMETER context_ptr AS MEMPTR.
END PROCEDURE.

DEF VAR mContext AS MEMPTR NO-UNDO.
RUN zmq_init(INPUT 0, OUTPUT mContext).

这个特定的函数初始化一个“0mq 上下文”(潜在问题:它是一个线程池)并返回一个指向它的指针。即使我正在调用外部库并请求在池中分配 0 个线程,该错误是否与 OpenEdge 的非线程性质有关?

在过程编辑器中运行代码会使其崩溃,并出现 Windows“Progress Client 已停止工作”错误Exception code: C0000005 ACCESS_VIOLATION(此处为完整堆栈跟踪,尽管我并不总是得到包含信息的堆栈跟踪)。

我从来没有做过 Windows C 编程,但如果我在 Unix 上使用 gcc(访问受保护的内存),它看起来就像我所说的分段错误。说到这一点,我实际上宁愿在 Unix 机器上运行这段代码,但显然 Progress 只为 Windows 提供评估开发人员 OE 环境:(。

我已经禁用了 DEP,但没有成功。当指针从库返回时,ABL 是否试图取消引用它?当然,必须有一种方法来处理返回值为 void* 的签名,这些签名在库调用中得到 malloc'ed。

我翻阅了OpenEdge Development: Programming Interfaces、Tom Bascom 的UNIX Shared Libraries PowerPoint 以及LDAP World 中的其他一些称为 OpenEdge 的PowerPoint,其中包含一些代码示例,但看不到任何明显我遗漏的内容。

我使用的是 OpenEdge 10.2B,Windows 7 64 位,但是使用 32 位版本的 OpenEdge 作为评估软件的唯一选择。任何人都有我可以借来在 CentOS 上编译/运行此代码的许可证吗?:-)

4

3 回答 3

2

声明过程时缺少PERSISTENT关键字。

请尝试以下代码:

zmq.p

&SCOPED DLLNAME 'libzmq.so'
PROCEDURE zmq_init EXTERNAL {&DLLNAME} CDECL PERSISTENT:
    DEF INPUT  PARAMETER NumThreads AS LONG.
    DEF RETURN PARAMETER Context AS MEMPTR.
END PROCEDURE.

PROCEDURE zmq_term EXTERNAL {&DLLNAME} CDECL PERSISTENT:
    DEF INPUT  PARAMETER Context  AS MEMPTR.
    DEF RETURN PARAMETER ResultStatus AS LONG.
END PROCEDURE.

PROCEDURE zmq_version EXTERNAL {&DLLNAME} CDECL PERSISTENT:
    DEF OUTPUT PARAMETER major AS LONG.
    DEF OUTPUT PARAMETER minor AS LONG.
    DEF OUTPUT PARAMETER patch AS LONG.
END PROCEDURE.

check_zmq.p

DEF VAR Zmq AS HANDLE NO-UNDO.
DEF VAR MajorVersion AS INT NO-UNDO.
DEF VAR MinorVersion AS INT NO-UNDO.
DEF VAR PatchVersion AS INT NO-UNDO.

DEF VAR CallStatus AS INT NO-UNDO.

DEF VAR ZmqContext AS MEMPTR NO-UNDO.

RUN zmq.p PERSISTENT SET Zmq.

RUN zmq_version IN Zmq ( OUTPUT MajorVersion, OUTPUT MinorVersion, OUTPUT PatchVersion ).
MESSAGE MajorVersion MinorVersion PatchVersion.

RUN zmq_init IN Zmq ( 1, OUTPUT ZmqContext ).
RUN zmq_term IN Zmq ( ZmqContext, OUTPUT CallStatus ).
MESSAGE CallStatus.

FINALLY:
    IF VALID-HANDLE(Zmq) THEN
         DELETE PROCEDURE Zmq.
END FINALLY.
于 2013-04-22T06:43:05.040 回答
1

该错误是否与 OpenEdge 的非线程性质有关,即使我正在调用 >external 库并请求在池中分配 0 个线程?

在我使用线程的一些 c# 方法(通过 clr 桥调用)时,我多次遇到相同的问题(Progress Client 已停止工作)。通过使用一些 c# 库类(AsyncOperation,AsyncCallback)隐藏线程的进度解决了这个问题,但大多数尝试导致进度运行时停止。

与 .net 相关的进度帮助指出“您不能使用 System.Threading.Thread 或任何派生类 — ABL 是单线程的。”

我知道通过 clr bridge 调用 c# 方法与调用 c 库完全不同,但也许我们的问题是由 OpenEdge 的单线程性质引起的。

于 2012-04-29T18:40:31.437 回答
1

我从 github 获取了您的代码并将 MEMPTR 变量更改为 INT64。这允许它在不崩溃的情况下运行(64 位 Windows 7 上的 10.2b05 32 位)。由于内存是由 zeromq 处理的,我认为这是处理问题的安全方法。

于 2012-05-02T18:23:50.200 回答