0

C コードでは、関数は次のように定義されます。

INT WINAPI myFunction(LPCTSTR str1, LPCTSTR str2, INT iNumber,
    LPSTRUCT *lpStruct);

*lpStructstruct 型のポインターの配列です。

typedef struct myStruct
{
CHAR                    m_s1[64];       
UINT                    m_nS;       
CHAR                    m_s2[8][64];    
UINT                    m_nP;
CHAR                    m_s3[512];

} SomeStruct, *LPSTRUCT;

myFunctionこれを C# で外部と呼ぶ必要があり、次のように定義SomeStructしました。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SomeStruct
{

   [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 64)]
   public string m_s1;             
   public uint m_nS;             
   [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
   public string m_s2;             
   public uint m_nP;
   [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
   public string m_s3;
 }

myFunction として:

[DllImport("some.dll")]
public static extern int myFunction(
             string str1,
             string str2,
             int iNumber,
             IntPtr[] lpStruct);

C# で IntPtr[] を初期化します。

IntPtr[] lpptr = new IntPtr[iNumber]; 

iNumberポインターの構造体配列に要素があることは知っています。

この関数を呼び出してもエラーはありません ( lpStruct[i]has number )。しかし、次を使用して構造体へのポインターをマーシャリングしようとしたとき:

SomeStruct st = (SomeStruct )Marshal.PtrToStructure(lpStruct[i], 
    typeof(SomeStruct ));

エラー メッセージが表示されました: 読み取り専用メモリに書き込んでください。ここで何が問題なのかわかりません。C# の外部関数の定義が間違っているか、構造体の定義が間違っているか、またはその両方ですか。

4

2 に答える 2

0

質問には重要な詳細が欠けていますが、配列内の各 IntPtr にメモリを割り当てる必要があると思います。

IntPtr[] lpptr = new IntPtr[iNumber];
for (int i=0; i<iNumber; i++)
    lpptr[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SomeStruct)));

そして明らかに、使い終わったらメモリを解放する必要があります。

于 2013-01-21T22:43:12.673 に答える
0

C# で Struct をクラスとして定義してみてください

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
internal class SomeStruct
{

   [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 64)]
   public string m_s1;             
   public UInt32 m_nS;             
   [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
   public string m_s2;             
   public UInt32 m_nP;
   [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 512)]
   public string m_s3;
}

uintの代わりにUInt32も試してください

于 2013-01-21T22:38:20.337 に答える