C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: C#からVC6DLLに構造体のchar[]を渡す


(過去ログ 21 を表示中)

[トピック内 22 記事 (1 - 20 表示)]  << 0 | 1 >>

■9091 / inTopicNo.1)  C#からVC6DLLに構造体のchar[]を渡す
  
□投稿者/ techno (1回)-(2007/10/18(Thu) 16:39:04)

分類:[C#] 

はじめまして、よろしくお願いします。
最近.NETはじめました。

VS2005のC#から、VC6で作成したDLLのAPI関数を呼ぶとき
「型 'stTest' のフィールド 'a' をマーシャリングできません:
無効なマネージ/アンマネージ型の組み合わせです。chars は I1、I2、U1、または U2
と組で使用してください。」
というエラーが出てしまいます。
MSDN等を参照しましたが、下のソースのどこが間違いなのかわからず困っています。

stTestという構造体は、DLL呼び出し後にC#側でデータをとる必要があります。

VC6DLL--------------------------

#pragma pack (4)
struct _stTest {
char a[1024];
int b;
char c[1024];
};
typedef struct _stTest stTest;
#pragma pack ()

int WINAPI test(long x, stTest *y);


VS2005C#--------------------------

[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public class stTest
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
public char a;
public int b;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
public char c;
}

[DllImport("test.dll")]
public static extern int test(int x, [Out] stTest y);

//呼び出し
int x = 1;
stTest y = new stTest();

if (0 < test(x, y)) { ←ここで前述のエラーが出てしまいます。


どなたかご教授お願いします。

引用返信 編集キー/
■9093 / inTopicNo.2)  Re[1]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ mあ (109回)-(2007/10/18(Thu) 16:56:23)
No9091 (techno さん) に返信
> #pragma pack (4)
> struct _stTest {
>     char a[1024];

この char と

> VS2005C#--------------------------
> 
> [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
> public class stTest
> {
>     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
>     public char a;

この char はサイズが違うのでは?

C# で、1バイトの型は、byte じゃなかったっけ?



VC6
int main() {

   char a = 'あ'; //<<== ここでエラー
   printf("%c", a);
}

C#
void main(String[] args) {
   char a = 'あ';
   Console.WriteLine("{0}", a);
}

引用返信 編集キー/
■9095 / inTopicNo.3)  Re[2]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ techno (2回)-(2007/10/18(Thu) 17:11:27)
No9093 (mあ さん) に返信
回答ありがとうございます。

> C# で、1バイトの型は、byte じゃなかったっけ?
とりあえず、byteに変えてみましたが、似たり寄ったりのエラーが出ます・・・

引用返信 編集キー/
■9096 / inTopicNo.4)  Re[3]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ Hongliang (198回)-(2007/10/18(Thu) 17:21:38)
Hongliang さんの Web サイト
a と c はどちらも配列ですから。
引用返信 編集キー/
■9098 / inTopicNo.5)  Re[4]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ mあ (110回)-(2007/10/18(Thu) 17:51:13)
No9096 (Hongliang さん) に返信
> a と c はどちらも配列ですから。

http://msdn2.microsoft.com/ja-jp/library/system.runtime.interopservices.unmanagedtype(VS.80).aspx

これ見てみた。

byte とか char とかそーゆー問題じゃないのね。

適当に合わせてくれるのか・・・

ってことで、

C# の方を

a[]
c[]
とかやったらいいんでない?

C# 配列 char VC6 で検索
http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=1243921&SiteID=7

帰ったら試してみますね。

# 自宅PCに C# も入れました。





引用返信 編集キー/
■9099 / inTopicNo.6)  Re[5]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ techno (3回)-(2007/10/18(Thu) 18:14:44)
No9098 (mあ さん) に返信
回答ありがとうございます。

C#のソースを以下に変更したら、当初のエラーは回避しました。

[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public class stTest
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
public char[] a;
public int b;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
public char[] c;
}

しかし、新たに「保護されているメモリに読み取りまたは書き込み操作を行おうとしました。
他のメモリが壊れていることが考えられます。」というエラーが出ました。

デバッグすると、aとcがnull参照?になってるみたいです。
メモリ割り当てたりしないと駄目なんですかね?調べてみます。



引用返信 編集キー/
■9100 / inTopicNo.7)  Re[6]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ Blue (350回)-(2007/10/18(Thu) 18:20:14)
>public char[] a;
>public char[] c;
ですからchar型ではなくbyte型です。
引用返信 編集キー/
■9101 / inTopicNo.8)  Re[7]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ techno (4回)-(2007/10/18(Thu) 18:37:07)
No9100 (Blue さん) に返信
> >public char[] a;
> >public char[] c;
> ですからchar型ではなくbyte型です。

失礼しました。
byte[]でやってみましたが、同様のエラーです。

また、
int x = 1;
stTest y = new stTest();
ここで、
y.a = new byte[1024];
y.c = new byte[1024];

if (0 < test(x, y)) {

とやっても同様です・・・


引用返信 編集キー/
■9102 / inTopicNo.9)  Re[8]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ Hongliang (199回)-(2007/10/18(Thu) 19:01:27)
Hongliang さんの Web サイト
あとは test 関数の処理次第です。
なお、各配列を new する必要はありません(Out であるなら)。
引用返信 編集キー/
■9109 / inTopicNo.10)  Re[9]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ mあ (112回)-(2007/10/19(Fri) 03:33:17)
2007/10/19(Fri) 03:43:01 編集(投稿者)
2007/10/19(Fri) 03:40:13 編集(投稿者)

No9102 (Hongliang さん) に返信


C++インストールから、さて、DLL作成だ・・・小2時間半程硬直してから、
http://watcher.moe-nifty.com/memo/2006/05/visual_studio_c_4427.html
コレ見て、PlatformSDK入れて、設定いじって・・・・長かった。。。

う、、、動きました。

すっからかんで忘れていました。。。。

extern "C" ですよね。
C++ですもん。

エントリポイントが見つかりません・・・なんで〜??DllMainちゃうの〜??〜

マーシャルのPInvokeがなんちゃらかんちゃら・・・って例外出ました。

構造体の受け渡しは明日、もう眠い。

呼び出し成功:int GetValue() { return 42; }
呼び出し失敗:Test* GetTest() { Test *t = new Test; t.b = 32; return t; }
struct Test {
char a[4];
int b;
char c[4];
};

補足:
あ、分かった、この前別スレでしぶきさんが書いていた、StructureToPtr だか、
アレ使うのかな、きっと。


引用返信 編集キー/
■9135 / inTopicNo.11)  Re[10]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ techno (5回)-(2007/10/19(Fri) 16:25:16)
2007/10/19(Fri) 16:29:11 編集(投稿者)
2007/10/19(Fri) 16:29:07 編集(投稿者)

とりあえず
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public class stTest
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
public byte[] a;
public int b;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
public byte[] c;
}
として、デバッグしていたら「保護されているメモリに読み取りまたは書き込み操作
を行おうとしました。他のメモリが壊れていることが考えられます。」というエラーが
出ていたんですが、ビルドして出来たEXEをtest.dllと同じディレクトリに入れ、EXEを実行
したら、上記エラーは出ず正常に処理されました。OUTのデータも正しく参照できます。

プロジェクトのプロパティの参照パスに、TEST.dllが入っているディレクトリを設定してデバッグして
いたんですが、上記エラーが出るのはなぜなんでしょう?
何かVS2005の設定が足りないんですかね?

引用返信 編集キー/
■9140 / inTopicNo.12)  Re[11]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ mあ (113回)-(2007/10/19(Fri) 17:22:44)
No9135 (techno さん) に返信
> 2007/10/19(Fri) 16:29:11 編集(投稿者)
> 2007/10/19(Fri) 16:29:07 編集(投稿者)
> したら、上記エラーは出ず正常に処理されました。OUTのデータも正しく参照できます。

おおお、動いてよかったですね〜。

>
> プロジェクトのプロパティの参照パスに、TEST.dllが入っているディレクトリを設定してデバッグして
> いたんですが、上記エラーが出るのはなぜなんでしょう?
> 何かVS2005の設定が足りないんですかね?

EXEのmain の適当などこかに、 カレントでぃれくとりを Console.WriteLine してみたら
どーでしょう?
もしかしたら、カレントディレクトリの設定とか関係・・・ないかな??


引用返信 編集キー/
■9146 / inTopicNo.13)  Re[12]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ techno (7回)-(2007/10/19(Fri) 17:47:48)
mあさん、お付き合い頂いてありがとうございます。

> EXEのmain の適当などこかに、 カレントでぃれくとりを Console.WriteLine してみたら
> どーでしょう?
> もしかしたら、カレントディレクトリの設定とか関係・・・ないかな??
>
試してみます。。が、デバッグするDLLがカレントに無いとエラーになるって
おかしくないですか?(^^;
引用返信 編集キー/
■9169 / inTopicNo.14)  Re[1]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ 渋木宏明(ひどり) (482回)-(2007/10/20(Sat) 03:33:41)
渋木宏明(ひどり) さんの Web サイト
> [DllImport("test.dll")]
> public static extern int test(int x, [Out] stTest y);

マネージで用意したメモリ(=配列)に値をセットして戻ってきてほしいんでしょ?
だとしたら、[Out] は変。ref か、[In,Out] が妥当。

ちゃんとマーシャリングのトピックを読めばわかるはず。

> stTest y = new stTest();

これじゃあ、構造体メンバになってる配列の分の領域が確保されませんぜ。

> アレ使うのかな、きっと。

この場合はハズレ。
アンマネージと、IntPtr 経由で構造体をやりとりする時に使います>StructToPtr/PtrToStruct

> VC6DLL--------------------------
>
> #pragma pack (4)
> struct _stTest {
> char a[1024];

この char 配列は、C# 側では文字列として扱いたいんですか?
それとも byte 配列として扱いたいんでしょうか?

それによって構造体や属性の記述を変える必要があります。
∵マーシャラに「文字列」なのか「byte 型の配列」なのかを伝えるため



引用返信 編集キー/
■9170 / inTopicNo.15)  Re[2]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ Hongliang (201回)-(2007/10/20(Sat) 08:49:26)
Hongliang さんの Web サイト
> マネージで用意したメモリ(=配列)に値をセットして戻ってきてほしいんでしょ?
> だとしたら、[Out] は変。ref か、[In,Out] が妥当。
In はこっちから向こうに渡すとき用意したメモリの内容をコピーする指示であって、単にメモリの内容を受け取るだけなら不要ですが。

> これじゃあ、構造体メンバになってる配列の分の領域が確保されませんぜ。
固定長なメンバのメモリの用意はマーシャラの仕事。

> この場合はハズレ。
> アンマネージと、IntPtr 経由で構造体をやりとりする時に使います>StructToPtr/PtrToStruct
mあさんの例の場合は IntPtr 経由しないとメモリ解放の機会が失われますよね。
引用返信 編集キー/
■9172 / inTopicNo.16)  Re[3]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ 渋木宏明(ひどり) (483回)-(2007/10/20(Sat) 10:33:40)
渋木宏明(ひどり) さんの Web サイト
>>これじゃあ、構造体メンバになってる配列の分の領域が確保されませんぜ。
> 固定長なメンバのメモリの用意はマーシャラの仕事。

う。メンバは string 型で、構造体自体は ref で渡すのが習慣になっちゃってるな>じぶん

>>アンマネージと、IntPtr 経由で構造体をやりとりする時に使います>StructToPtr/PtrToStruct
> mあさんの例の場合は IntPtr 経由しないとメモリ解放の機会が失われますよね。

い? どこの分です?

引用返信 編集キー/
■9173 / inTopicNo.17)  Re[4]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ Hongliang (202回)-(2007/10/20(Sat) 10:54:39)
Hongliang さんの Web サイト
>>mあさんの例の場合は IntPtr 経由しないとメモリ解放の機会が失われますよね。
>
> い? どこの分です?

これですね。
> Test* GetTest() { Test *t = new Test; t.b = 32; return t; }

まあ DLL 側に FreeTest とかがなかったらどのみち無理ですが。
引用返信 編集キー/
■9179 / inTopicNo.18)  Re[5]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ 渋木宏明(ひどり) (485回)-(2007/10/20(Sat) 12:20:06)
渋木宏明(ひどり) さんの Web サイト
> これですね。
>>Test* GetTest() { Test *t = new Test; t.b = 32; return t; }
>
> まあ DLL 側に FreeTest とかがなかったらどのみち無理ですが。

C++ で new したブツを返しちゃってるから、C++ で解放する手段を用意しないとだめですね。


引用返信 編集キー/
■9189 / inTopicNo.19)  Re[6]: C#からVC6DLLに構造体のchar[]を渡す
□投稿者/ mあ (115回)-(2007/10/20(Sat) 21:08:21)
No9179 (渋木宏明(ひどり) さん) に返信
>>これですね。
> >>Test* GetTest() { Test *t = new Test; t.b = 32; return t; }
> >
>>まあ DLL 側に FreeTest とかがなかったらどのみち無理ですが。
>
> C++ で new したブツを返しちゃってるから、C++ で解放する手段を用意しないとだめですね。
>
>

こちらの勉強にまで意見していただきありがとうございます。m(__)m
ポインタ返す場合には、PtrToStruct 使えるのですよね。って逆質問しているあたり全然試して
いないのが現状だったりするのですがw

とりあえず、MSDNは見るのはいいですが理解しにくい部分も多々あるので
ちゃんとした日本語に意訳してもらえるだけでもありがたく感じています。




引用返信 編集キー/
■9190 / inTopicNo.20)  Re[7]: C#からVC6DLLに構造体のchar[]を渡す
 
□投稿者/ 渋木宏明(ひどり) (486回)-(2007/10/20(Sat) 22:34:29)
渋木宏明(ひどり) さんの Web サイト
> ポインタ返す場合には、PtrToStruct 使えるのですよね。

は、まぁそうなんですけど、その前に new/malloc で確保した領域を .dll/.exe 境界を越えて引き渡すのはあまりよいことではありません。原則避けるべきです。

new/malloc は C ランタイムが管理するヒープから領域確保を行うため、.dll/.exe 境界を越えて渡された側では一般に、その領域を正しく解放する術がありません。

> とりあえず、MSDNは見るのはいいですが理解しにくい部分も多々あるので
> ちゃんとした日本語に意訳してもらえるだけでもありがたく感じています。

ん? .NET 関係は基本的にほとんど和訳されてますよね?

和訳された文章が分かりにくいといことですか?

引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -