如何将C#中的方法指针传递到C库?

如何将C#中的方法指针传递到C库?,c#,.net,linux,.net-core,casting,C#,.net,Linux,.net Core,Casting,有人知道如何将C#中的方法强制转换为void*成员吗 在下面的示例中,sigaction.sa_处理程序是指定回调函数的void*成员 环境: VisualStudio专业版2019 16.9.4 dotnet核心SDK 3.1 WSL上的Ubuntu Tmds.Linux 0.5.0 sigaction-sigact=new-sigaction(); //错误CS0428无法将方法组“catcher”转换为非委托类型“void*”。是否要调用该方法? sigact.sa_handler=c

有人知道如何将C#中的方法强制转换为void*成员吗

在下面的示例中,sigaction.sa_处理程序是指定回调函数的void*成员

环境:

  • VisualStudio专业版2019 16.9.4
  • dotnet核心SDK 3.1
  • WSL上的Ubuntu
  • Tmds.Linux 0.5.0
sigaction-sigact=new-sigaction();
//错误CS0428无法将方法组“catcher”转换为非委托类型“void*”。是否要调用该方法?
sigact.sa_handler=catcher;
//错误CS0030无法将类型“method”转换为“void*”
sigact.sa_handler=(void*)catcher;
//错误CS0029无法将类型“SignalCallback”隐式转换为“void*”
SignalCallback=新的SignalCallback(捕捉器);
sigact.sa_handler=回调;
//错误CS0030无法将类型“SignalCallback”转换为“void*”
sigact.sa_handler=(void*)回调;
sigaction的结构(来自Tmds.Linux)

public结构sigaction
{
公共信号屏蔽;
public void*sa_处理程序{get;set;}
public void*sau sigaction{get;set;}
公共int sau标志{readonly get;set;}
public void*sa_restorer{readonly get;set;}
}
完整源代码:

使用系统;
使用静态Tmds.Linux.LibC;
使用Tmds.Linux;
使用System.Runtime.InteropServices;
委托无效信号回调(int sig);
名称空间示例
{
班级计划
{
静态空隙捕集器(int sig)
{
Write($“为信号{sig}调用的信号捕捉器”);
}
静态无效时间戳(字符串str)
{
Write($“时间{str}是{DateTime.Now}”);
}
静态不安全int Main(字符串[]args)
{
int结果=0;
sigaction sigact=新的sigaction();
sigset_t waitset=新sigset_t();
siginfo_t info=新siginfo_t();
sigset_t*ptr=&sigact.sa_掩码;
sigemptyset(&sigact.sa_mask);
sigact.sa_标志=0;
//错误CS0428无法将方法组“catcher”转换为非委托类型“void*”。是否要调用该方法?
sigact.sa_handler=catcher;
//错误CS0029无法将类型“SignalCallback”隐式转换为“void*”
SignalCallback=新的SignalCallback(捕捉器);
sigact.sa_handler=回调;
sigaction(SIGALRM和sigact,null);
sigemptyset(&waitset);
sigaddset(&waitset,SIGALRM);
sigprocmask(SIG_块和等待集,null);
警报(10);
时间戳(“在sigwaitinfo()之前”);
结果=sigwaitinfo(&waitset,&info);
如果(结果==SIGALRM)
WriteLine($“sigwaitinfo()为信号{info.si_signo}返回);
其他的
{
WriteLine($“sigwait()返回代码{result}”);
WriteLine($“sigwait()返回错误号{errno}”);
WriteLine(“sigwait()函数失败”);
}
时间戳(“在sigwaitinfo()之后”);
返回结果;
}
}
}

要从委托获取
void*
指针,您需要
Marshal.GetFunctionPointerForDelegate
。必须确保委托在最终使用前未被垃圾收集您可以为此使用
GC.KeepAlive

SignalCallback=newsignalcallback(catcher);
sigact.sa_handler=Marshal.GetFunctionPointerForDelegate(回调);
//做你剩下的事
//非托管代码上次使用后
GC.KeepAlive(回调);

但是:

您应该更加依赖p/Invoke来进行任何转换。在大多数情况下,它应该能够对
void*
转换进行排序,您只需要
GC.KeepAlive

您当前的代码有很大的问题,因为您将托管指针投射到整个
void*

例如,不是此调用,而是执行从
&
托管指针到
void*

sigeptypyset(&waitset);
相反,你会使用

sigeptypyset(参考waitset);
理想情况下,结构不应该使用属性,因为这样会使在字段上定义属性变得更加困难。我注意到,
sigaction
的顺序似乎不正确,从我快速的谷歌上可以看出

您应该这样定义
sigaction

public结构sigaction
{
公共信号处理器;
公共信号行动;
公共信号屏蔽;
国际国旗;
公共信号恢复器sa_恢复器;
}

要从委托获取
void*
指针,您需要
Marshal.GetFunctionPointerForDelegate
。必须确保委托在最终使用前未被垃圾收集您可以为此使用
GC.KeepAlive

SignalCallback=newsignalcallback(catcher);
sigact.sa_handler=Marshal.GetFunctionPointerForDelegate(回调);
//做你剩下的事
//非托管代码上次使用后
GC.KeepAlive(回调);

但是:

您应该更加依赖p/Invoke来进行任何转换。在大多数情况下,它应该能够对
void*
转换进行排序,您只需要
GC.KeepAlive

您当前的代码有很大的问题,因为您正在将托管指针投射到
void*
all ov