将结构内部的整数指针编组为回调

时间:2017-03-14 11:55:03

标签: c# .net c callback marshalling

我有一个用于回调的C结构,我需要编组到C#.NET:

public static int connettiti()
    {
        Random rand = new Random();
        int ID = rand.Next(1, 999999);
        giocatori.Add(ID);
        contagiocatori++;
        if (giocatori.Count == 0)
        {
            codicevincitore = ID;
        }
        else if (giocatori.Count > 2)
        {
            return 1000000;
        }
        return ID;
    }
    public static bool avviare()
    {
        bool avvia = false;
        int count = giocatori.Count;
        if (count == 2)
        {
            avvia = true;
        }
        return avvia;
    }

这是我的C#版本:

struct CTMDeviceInfo {
    enum CTMDeviceType eDeviceType;
    char *             szDeviceModel;
    char *             szDeviceSubModel;
    int32_t *          piDeviceID;
};

在另一个结构中使用:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CTMDeviceInfo
{
    public CTMDeviceType deviceType;

    [MarshalAs(UnmanagedType.LPStr)]
    public string deviceModel;

    [MarshalAs(UnmanagedType.LPStr)]
    public string deviceSubModel;

    public IntPtr deviceId;
};

我的问题是" IntPtr deviceId"每次回调时都不会始终返回正确的值。

我期待一个5,15或16的整数值,但它会不断返回106,865412,652272等随机值。

我不知道自己做错了什么。我所做的是阻止我的托管代码中的回调使用GCHandle进行垃圾收集。

以下是我如何做到的顺序:

从我的非托管代码中我有这个CDECL回调方法:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CTMDeviceError
{
    public CTMDeviceInfo deviceInfo;

    [MarshalAs(UnmanagedType.I4)]
    public Int32 resultCode;

    [MarshalAs(UnmanagedType.I4)]
    public Int32 extendedResultCode;

    public IntPtr denomination;

    public IntPtr changeDue;
}; 

这是我的托管代码:

void ctm_add_device_error_event_handler(CTMDeviceErrorCallback);

typedef void (CTMDeviceErrorCallback) (struct CTMEventInfo, struct CTMDeviceError );

这就是处理回调的地方:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void OnDeviceErrorCallBack(CTMEventInfo evtInfo, CTMDeviceError deviceError);

[DllImport("libctmclient-0.dll", EntryPoint = "ctm_add_device_error_event_handler", CallingConvention = CallingConvention.Cdecl)]
public static extern void AddDeviceErrorEventHandler([MarshalAs(UnmanagedType.FunctionPtr)] OnDeviceErrorCallBack deviceErrorCallBack);

OnDeviceErrorCallBack deviceErrorCallback;
GCHandle deviceErrorCallbackGCHandle;

deviceErrorCallback = new OnDeviceErrorCallBack(OnDeviceError);
deviceErrorCallbackGCHandle = GCHandle.Alloc(deviceErrorCallback);
AddDeviceErrorEventHandler(deviceErrorCallback);

我尝试使用unsafe直接使用指针但问题仍然相同。

public void OnDeviceError(CTMEventInfo evtInfo, CTMDeviceError deviceError)
{
    int nDeviceId = Marshal.ReadInt32(deviceError.deviceInfo.deviceId);
}

我确定我的非托管代码返回了正确的值,因为我有日志但是当它在托管代码中到达时,不知何故返回了另一个值。 它就像阅读不同的参考文献或其他东西。

希望有点可以帮助我,因为我现在已经被困了一段时间。 谢谢!

1 个答案:

答案 0 :(得分:0)

使用以下c#结构。您可以稍后在代码中从指针获取两个字符串。 :

@media(max-width: 640px){
  table, table td, table tr, table th { display: block; text-align: left; } 
  table th, table td { margin: 0; padding-left: 25px;  }
  table td  { margin-left: 40px;list-style: square; display: list-item; padding-left: 0; }
  table thead { display: none; }
}