将托管事件处理程序传递给 Linux 中的非托管代码

Passing managed event handler to unmanaged code in Linux

本文关键字:Linux 非托管代码 事件处理 程序      更新时间:2023-10-16

我一直在为将在Linux下运行的现有C++库编写.Net Core C#包装器。该库具有以下内容:

int newrelic_record_metric(const char *name, double value);
void newrelic_register_message_handler(void*(*handler)(void*));
void *newrelic_message_handler(void *raw_message);

第一种方法很容易包装:

internal static class AgentSdkWrapper {
    [DllImport("newrelic-transaction")]
    public static extern unsafe int newrelic_record_metric(StringBuilder name, double value);

我正在为第二个版本的签名而苦苦挣扎,我不知道如何将其转换为 C#。我知道我正在处理空指针,但我不确定如何处理它们。

另外,根据库文档,我需要将第三个方法注册为第二个方法的回调:

您必须注册所需的回调,该回调将在事务完成时将数据发送到New Relic。您需要注册已定义的默认newrelic_message_handler回调:

newrelic_register_message_handler(newrelic_message_handler(;

我认为我需要将newrelic_message_handler分配给 C# 委托并将其传递给 newrelic_register_message_handler ,但我不清楚我是如何到达那里的。

如果我

正确理解了文档,您只需要将指向第二个函数的指针传递给newrelic_message_handler

这意味着对于所有意图和目的,您的第二个函数将如下所示:

[DllImport(...)]
static extern void newrelic_register_message_handler(IntPtr handler);

因为实际上你只是传递一个指针,并不真正关心类型。

要获取指向newrelic_message_handler的指针(假设这是一个 dll 导出函数(,您需要使用 GetProcAdress

[DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr LoadLibrary(string lpFileName);

您的最终代码将是:

var module = LoadLibrary("newrelic-transaction");
var proc = GetProcAddress(module, "newrelic_message_handler");
newrelic_register_message_handler(proc);