- PR -

[C#] 構造体のポインタを返すDLLから構造体を受け取る

1
投稿者投稿内容
ペンちゃん
ベテラン
会議室デビュー日: 2006/08/04
投稿数: 61
投稿日時: 2006-08-04 14:57
初めましてペンちゃんといいます。VS2005でC#からCのDLL関数を呼び出そうとしています。
過去ログなども検索しましたが解決に至らなかったので質問させてください。

C#にてCで作られたDLLの関数を呼び出し、引数に渡された構造体のポインタから元の構造体を受け取ろうとしています。
受け取る構造体、呼び出す関数は以下のようになっています。

typedef struct {
  unsigned int num;
  struct {
    char name[ 20 ];
  } stB[ 1 ];
} stA_t, *stA_p;

int getname(stA_p *outList);//呼び出す関数

これに対しC#で以下のように受け取ろうとしています。

[C#]
[StructLayout(LayoutKind.Sequential)]
struct stA{
  public UInt32 num;
  public IntPtr stB;
}

[DllImport("c.dll", EntryPoint = "getname", CharSet = CharSet.Ansi)]
private static extern int c_getname( ref stA outList );
・・・
stA outList = new stA();
IntPtr pt = IntPtr.ZERO;
int ret = c_getname( ref pt );
outList = (stA)Marshal.PtrToStructure(pt, typeof(stA));

このように実行すると、outList.numは正しい値が取得できるのですが、
stBの方はstBへのポインタではなくstB[0].nameのデータ4バイト分が取得されてしまいます。

返って来るデータとしてはデータの個数numとstBの配列がnum個分となっています。
stBのポインタが取得できればあとはnumの値分だけstBを取り出せばいいのかなと思います。
どのようにすればstBの配列が正常に取得できるでしょうか?
(そもそもstBのポインタを受け取るという考えはあっているのでしょうか?)

分かる方がいらっしゃいましたらご助言いただけると幸いです。

[ メッセージ編集済み 編集者: ペンちゃん 編集日時 2006-08-04 15:17 ]
Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2006-08-04 15:32
可変長メンバを持つ構造体はC側から見れば扱いやすいのですが、それ以外だと
構造体のサイズが取得時に決まらないのでやりにくいですね。

C#側では最初の取得は、IntPtrでとりあえず受けておいて、
C#では構造体を用意せず、最初にIntPtrから先頭のnumの値を取得し、
取得したnumの値によって、最初に受けておいたInPtrをずらして
Byte[20]*numの領域の値を取得する。


てな具合にしてみてはどうでしょうか?
ペンちゃん
ベテラン
会議室デビュー日: 2006/08/04
投稿数: 61
投稿日時: 2006-08-04 16:05
Blue様、早速のご助言ありがとうございます。

引用:

可変長メンバを持つ構造体はC側から見れば扱いやすいのですが、それ以外だと
構造体のサイズが取得時に決まらないのでやりにくいですね。


そうなんですよね。呼んでみるまで分からないので事前に準備ができないですよね。

引用:

C#側では最初の取得は、IntPtrでとりあえず受けておいて、
C#では構造体を用意せず、最初にIntPtrから先頭のnumの値を取得し、
取得したnumの値によって、最初に受けておいたInPtrをずらして
Byte[20]*numの領域の値を取得する。

てな具合にしてみてはどうでしょうか?


なるほど。これなら可変長でも扱えますね。
早速試してみたところ無事にnameも取得することができました。
本当にありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)