2017-11-01 11 views
3

申し訳ありませんが、私は明確ではありません。C#コードでコールバックに渡されたC/C++ネイティブ構造体の使用方法

私はいくつかのビデオカメラSDKを使用していますので、カメラビューをブロックするオブジェクトなどいくつかのアラームを警告する必要があります。 SDKには、アラートを受け取るための登録機能があります。 この関数は、休閑の通りです:

H264_DVR_SetDVRMessCallBack(fMessCallBack cbAlarmcallback, unsigned long lUser); 

cbAlarmCallbackは休閑の通りです:

bool __stdcall MessCallBack(long lLoginID, char *pBuf, 
          unsigned long dwBufLen, long dwUser) 
{ 
    return DealwithAlarm(lLoginID,pBuf,dwBufLen); 

} 
//Note here char *pBuf, in c++ its declared as char* but it needs to be memcpy to SDK_AlarmInfo struct, this is declared in c++ as fallows: 
//alarm information 
typedef struct SDK_ALARM_INFO 
{ 
    int nChannel; 
    int iEvent; ///< refer to SDK_EventCodeTypes 
    int iStatus; ///< 0: start 1: stop 
    SDK_SYSTEM_TIME SysTime; 
}SDK_AlarmInfo; 

typedef struct SDK_SYSTEM_TIME{ 
    int year;///< year 
    int month;///< month,January = 1, February = 2, and so on. 
    int day;///< day 
    int wday;///< week, Sunday = 0, Monday = 1, and so on 
    int hour;///< hour 
    int minute;///< minute 
    int second;///< second 
    int isdst;///< DST(daylight saving time) flag, Yes = 1, No = 0 
}SDK_SYSTEM_TIME; 

DealwithAlarm機能:

void CClientDemoDlg::DealwithAlarm(long lDevcID, char* pBuf , DWORD dwLen) 
{ 
     SDK_AlarmInfo alarmInfo; 
     memcpy (&alarmInfo, pBuf, dwLen); 

    if ((SDK_EVENT_CODE_NET_ALARM == alarmInfo.iEvent)) 
    { 
    // Do something 
    } 
} 
このすべては、C++で完全に正常に動作している

、およびCHAR * PBUF問題のないSDK_AlarmInfoに変換されます。

C#では私がやっている:

public delegate bool fMessCallBack(int lLoginID, byte[] pBuf, uint dwBufLen, IntPtr dwUser); 

[DllImport("NetSdk.dll")] 
     public static extern void H264_DVR_SetDVRMessCallBack(fMessCallBack cbAlarmcallback, IntPtr lUser); 

パブリック構造体SDK_ALARM_INFO { int型Nチャネルを。 int iEvent; // SDK_EventCodeTypeを参照してください int iStatus; // 0:開始1:停止 SDK_SYSTEM_TIME SysTime; } C#のコードで

public struct SDK_SYSTEM_TIME 
{ 
    public int year;// 
    public int month;//January = 1, February = 2, and so on. 
    public int day;// 
    public int wday;//Sunday = 0, Monday = 1, and so on 
    public int hour;// 
    public int minute;// 
    public int second;// 
    public int isdst;// 
} 

    public enum SDK_EVENT_CODE_TYPES 
    { 
     SDK_EVENT_CODE_INIT = 0, 
     SDK_EVENT_CODE_LOCAL_ALARM = 1, //local alarm 
     SDK_EVENT_CODE_NET_ALARM,  //network alarm 
     SDK_EVENT_CODE_MANUAL_ALARM, //manual alarm 
     SDK_EVENT_CODE_VIDEO_MOTION, //motion detect 
     SDK_EVENT_CODE_VIDEO_LOSS,  //loss detect 
     SDK_EVENT_CODE_VIDEO_BLIND,  //blind detect  
    } 
    public int Init() 
    { 
     fMessCallBack msgcallback = new fMessCallBack(MessCallBack); 
     H264_DVR_SetDVRMessCallBack(msgcallback, dwUser); 


    } 
    bool MessCallBack(int lLoginID, byte[] pBuf, uint dwBufLen, IntPtr dwUser) 
    { 
     SDK_ALARM_INFO alarmInfo; 
     //here i should translate pBuf param into alarm Info 

     return true; 
    } 

MessCallBack機能がSDKによって呼び出されて、ここに私の問題は、私はSDK_ALAM_INFO構造としてalarmInfoを読み取ることができませんよということですので、私は、この構造体の値の内側から読み取ることができませんアラームが発生した時刻や発生したアラームの種類と同様です。

私は本当に助けに感謝します。先にありがとう

+6

C/C++コードのようなものはありません。誰もあなたに別のことを教えてはいけません。マイクロソフトでさえない – Ron

+0

C#のバージョンでは、文字列を返すこともできます。 – byxor

+3

あなたはC#コードを表示する方が良いかもしれません。関数の翻訳で言葉や関数で言葉をすることはできません。 'DealwithAlarm'は' alarm '以外のものを扱っていますか? – doctorlove

答えて

4

解決しなければならない問題は、ネイティブ構造をC#構造にマーシャリングすることです。最初のステップは、C/C++構造体をC#構造体に正確にマッピングすることです。上記マッピングで

[StructLayout(LayoutKind.Sequential)] 
public struct SDK_ALARM_INFO 
{ 
    int nChannel; 
    int iEvent; //refer to SDK_EventCodeType 
    int iStatus; // 0: start 1: stop 
    SDK_SYSTEM_TIME SysTime; 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct SDK_SYSTEM_TIME 
{ 
    public int year; 
    public int month; 
    public int day; 
    public int wday; 
    public int hour; 
    public int minute; 
    public int second; 
    public int isdst; 
} 

2つの問題がある:iEventの大きさがCの両方として時には未知であってもよく、C++列挙は、列挙値が収まるた最小の整数型を適合させるであろう。したがって、このタイプとして構造体内で宣言されている場合、iEventサイズはC/C++ SDK_EventCodeTypeの定義に依存することがあります。 C#への変換が、SDK_EventCodeTypeよりも列挙値全体の集合を表す場合は、1バイトのサイズになります。構造体は、として宣言されます場合は、次の構造体のサイズとレイアウトより

typedef struct SDK_ALARM_INFO 
{ 
    int nChannel; 
    SDK_EventCodeType iEvent; ///< refer to SDK_EventCodeTypes 
    int iStatus; ///< 0: start 1: stop 
    SDK_SYSTEM_TIME SysTime; 
}SDK_AlarmInfo; 

コード・リストに示された方法で宣言した場合よりも異なるだろう。しかし、このケースはおそらくここには存在しません。私はこのbcsについて書いています。SDKのハードウェアにこの種のエラーが発生しました。その問題を避けるために、私はiEventiStatusの宣言とSDKの他の場所での使用を再確認します。

SDK_SYSTEM_TIME型の宣言では、マネージドカウンターパートも作成する必要があります。最初のコードリストの構造の宣言は、相互運用中に使いやすくするために調整することができます。変更された宣言は[StructLayout(LayoutKind.Explicit)][FieldOffset(12)]属性の助けを借りてfixed Arrayの使用状況やunionなどのC/C++の作成を示しています

[StructLayout(LayoutKind.Explicit)] 
public unsafe struct SDK_ALARM_INFO 
{ 
    [FieldOffset(0)] 
    int nChannel; 
    [FieldOffset(4)] 
    int iEvent; //refer to SDK_EventCodeType 
    [FieldOffset(8)] 
    int iStatus; // 0: start 1: stop 
    [FieldOffset(12)] 
    SDK_SYSTEM_TIME SysTime; 
    [FieldOffset(12)] 
    fixed int Time[8]; 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct SDK_SYSTEM_TIME 
{ 
    public int year; 
    public int month; 
    public int day; 
    public int wday; 
    public int hour; 
    public int minute; 
    public int second; 
    public int isdst; 
} 

構造の最後のフィールドがfixed int Time[8]SDK_SYSTEM_TIMEの労働組合です。ネイティブデータを整列化するための共用体を作成する必要はありません。SDK_SYSTEM_TIMEまたはfixed int Time[8]のいずれかで動作します。

最後に私たちのstruct SDK_ALARM_INFOにコールバックに渡されたネイティブポインタからの変換がへの呼び出しを達成することができる。このような場合にマーシャリングの最も難しい部分は、正確のメモリレイアウトを反映する管理構造を作成することです

var result = Marshal.PtrToStructure<SDK_ALARM_INFO>((IntPtr)pBuff); 

ネイティブ構造。

冒頭に有用な技術の一つが正しい表現をチェックするためにネイティブ側で管理側とsizeof(T)offsetof (type,member)Marshal.SizeOf<T>()方法の使用ADN [StructLayout(LayoutKind.Explicit)]属性である可能性があります。

+0

こんにちは、本当にありがとうございます。 私のC#宣言。 public struct SDK_SYSTEM_TIME { public int year; // public int month; // January = 1、February = 2などとなります。 public int day; // public int wday; //日曜日= 0、月曜日= 1など public int hour; public int minute; public int second; public int isdst; } – Gilbert

+0

@ギルバート:質問を編集して、SDK_SYSTEM_TIMEのコードリスト宣言に追加できますか?あなたのC/C++構造体の完全な管理構造表現を作成します。 –

+0

申し訳ありませんが、私はこの事で本当に新しいです。 – Gilbert

関連する問題