2012-04-30 14 views
2

構造体の配列をC++からC#に渡す必要があります。私は最初に一時的な構造を作成し、memcpyそれはC#側の構造のアドレスにそれを行う次のコードがあります。私は、同じ順序の要素で両側に構造を定義しました。構造体の配列をC#からC++に渡す

一時的な構造体が正しく埋め込まれていることを確認すると、temp_buf(ターゲット変数のアドレス)が繰り返しごとに構造体のサイズが増え、エラーは返されません。

ただし、配列の最初の項目のみがC#側に設定されています。ここで

は、C#側で定義している:

[DllImport(@"MyAwesomeDLL.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "[email protected]@[email protected]@@Z", CharSet = CharSet.Auto)] 
public static extern Int32 GetCoolDevices(out UInt32 p_deviceCount, out Device_s p_devicesBuf); 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
public struct Device_s 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 51)] 
    public String DeviceName; 
    public UInt32 DeviceID; 
} 
ここ

は、C++側で定義している:

#pragma pack (1) 
typedef struct 
{ 
    TCHAR device_name [51]; 
    UINT32 device_rid; 
} DEVICE_S; 


int GetDevices (UINT32 *device_count, DEVICE_S *devices_buf) 
{ 
.... 

    while(....) 
    { 
     DEVICE_S tmp_device; 
     memset(&tmp_device, 0, sizeof(DEVICE_S)); 

     tmp_device.device_id = 5; 
     sprintf(tmp_device.device_name, "a string"); 

     DEVICE_S *temp_buf = &(devices_buf[i]); 
     size_t mysize = sizeof(DEVICE_S); 
     memcpy(temp_buf, &tmp_device, mysize); 

     i++; 
     getNextDevice(); 
    } 

..... 
} 

そして、ここでは、私はそれを呼び出す方法です:

UInt32 MyDecDeviceCnt = 0; 
Device_s[] MyDecDevices = new Device_s[10]; 
int ret = GetCoolDevices(out MyDecDeviceCnt, out MyDecDevices[0]); 

ご提案いただきありがとうございます!

+0

@ SamFisher83 - あなたの提案は理にかなっていません。文字列の使用は正しい手順です。もちろん、2つの構造は同じサイズではなく、C#構造は少なくとも12ビット大きくなります。 –

+0

@Ramhound私は誤植を修正しました。 device_nameの長さは51文字です。まだ不一致はありますか? – mustafa

答えて

2

作成したAPIに問題があります。管理側(10要素)の配列のメモリを割り当てますが、配列の要素数を管理されていない側に渡すことはありません。マーシャラーは、10要素をマーシャリングする必要があると判断する方法がなく、アンマネージコードは書き込むバッファのサイズを知りません。

MarshalAsAttribute.SizeParamIndexを使用して、マーシャラにアレイのサイズに関する情報を提供できます。また、記事Default Marshaling for Arraysを見てください。 (特にCスタイルの配列に関する情報)

APIの性質上、非管理側にメモリが割り当てられるように変更することができます。管理対象側でメモリを解放できるようにするには、安全な配列またはhglobalを使用する必要があります。

+1

また、 'TCHAR device_name [20];'対 'SizeConst = 51' - これは' DeviceID'を間違ったオフセットに置く原因となります。 – ildjarn

+0

それは単純なタイプミスだと思っていましたが、修正する必要があります。 –

+0

@MartinLiversage - そのエラーが誤字になる可能性は低いです。 –

関連する問題