将c#结构封送到c结构不起作用



我想从C#调用下面的C函数,但它不起作用。C代码是.so文件的一部分。在我的情况下,代码应该在Linux环境中运行!

C#代码是控制台应用程序的一部分,该应用程序使用.so文件

/**
* brief Register a tag callback functions.
* param callback:  tag callback functions.
* return None
*/
extern void nfcManager_registerTagCallback(nfcTagCallback_t *callback);

以下是所需参数的定义:(C代码)

/**
* brief NFC Tag callback function structure definition.
*/
typedef struct {
/**
* brief NFC Tag callback function when tag is detected.
* param pTagInfo       tag infomation
*/
void (*onTagArrival) (nfc_tag_info_t *pTagInfo);
/**
* brief NFC Tag callback function when tag is removed.
*/
void (*onTagDeparture) (void);
}nfcTagCallback_t;

这是nfc_tag_info_t的定义:(C代码)

/**
* brief NFC tag information structure definition.
*/
typedef struct
{
/**
*  brief indicates the technology of tag
*/
unsigned int technology;
/**
*  brief the handle of tag
*/
unsigned int handle;
/**
*  brief the uid of tag
*/
char uid[32];
/**
*  brief the uid length
*/
unsigned int uid_length;
/**
*  brief activated protocol
*/
tNFC_PROTOCOL protocol;
}nfc_tag_info_t;

我尝试了以下操作:(C#代码)

[DllImport("libnfc_nci_linux.so", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
private static extern void nfcManager_registerTagCallback(IntPtr callback);

[StructLayout(LayoutKind.Sequential)]
public struct nfcTagCallback_t
{
[MarshalAs(UnmanagedType.FunctionPtr)]
public IntPtr onTagArrival;
[MarshalAs(UnmanagedType.FunctionPtr)]
public IntPtr onTagDeparture;
}
public static void onArrival(IntPtr intPtr)
{
Console.WriteLine("Arrival");
}
public static void onDeparture()
{
Console.WriteLine("Departure");
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackOnArrival(IntPtr intPtr);

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackOnDeparture();
[StructLayout(LayoutKind.Sequential)]
private struct nfc_tag_info_t
{
/**
*  brief indicates the technology of tag
*/
public uint technology;
/**
*  brief the handle of tag
*/
public uint handle;
/**
*  brief the uid of tag
*/
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] uid;
/**
*  brief the uid length
*/
public uint uid_length;
/**
*  brief activated protocol
*/
public byte protocol;
}

我把这个方法叫做

var nfcTagCallback = new nfcTagCallback_t();
nfcTagCallback.onTagDeparture = Marshal.GetFunctionPointerForDelegate(new CallbackOnDeparture(onDeparture));
nfcTagCallback.onTagArrival = Marshal.GetFunctionPointerForDelegate(new CallbackOnArrival(onArrival));
IntPtr testPointer = Marshal.AllocHGlobal(Marshal.SizeOf(nfcTagCallback));
Marshal.StructureToPtr(nfcTagCallback, testPointer, true);
nfcManager_registerTagCallback(testPointer); // <-- Exception (see below)

如果运行此代码,将引发以下异常:

Unhandled exception. System.ArgumentException: Type 'PN7150_NFC.Program+nfcTagCallback_t' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
at System.Runtime.InteropServices.Marshal.SizeOfHelper(Type t, Boolean throwIfNotMarshalable)
at System.Runtime.InteropServices.Marshal.SizeOf[T](T structure)
at PN7150_NFC.Program.Main(String[] args) in /home/pi/Desktop/PN7150-NFC/PN7150-NFC/Program.cs:line 95

有人能帮我吗?

您正在尝试将IntPtr封送为FunctionPtr,这应该用于委托。您可以:

  1. 定义onTagArrivalCallbackOnArrival,定义onTagDepartureCallbackOnDeparture
  2. 移除[MarshalAs(UnmanagedType.FunctionPtr)]

最后,正如@jdweng在评论中指出的那样,小心调用约定。

最新更新