![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
教えてください!
C++のアンマネージドDLLから、複数のファイル名(文字列)をC#に渡したいです。
ステップとしては、
C#から、C++のDLLの関数を最初に呼んで、コールバック関数を渡しています。
次に、DLLからコールバック関数を呼ぶ時に、複数のファイル名を渡したいです。
以下のコードを動かすと、、
C++からは2つ渡しているつもりなのに、
C#ではfilesがサイズ1のString配列として引数に入ってきます。
なぜでしょう?
またどうすればC#から複数受け取れるでしょうか?
教えてください!
C#
public delegate int StringArrayCallback(String[] files);
// C# -> C++
public static int start() {
StringArrayCallback cb = new StringArrayCallback(onReceivedFiles);
int ret = start(cb);
return ret;
}
// C++ -> C# callback
public static int onReceivedFiles(String[] files)
{
return 1;
}
C++コード
typedef int (__stdcall *OnReceivedFilesProc )(char**);
int start( OnReceivedFilesProc callback ) {
std::string message1_ = "from C++1";
std::string message2_ = "from C++2";
char* messages_[2] = { (char*)message1_.c_str(), (char*)message2_.c_str() };
int ret_ = callback(messages_);
std::cout << "[from c#]" << ret_;
}
No.2ベストアンサー
- 回答日時:
もうひとつの手段としてはやはりデリゲートの定義などを変更せざるを得ないのですがマーシャリング手段を指示しましょう
public delegate int StringArrayCallback2([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 1)] string[] files, int n);
とします nには配列の個数が返されます
と定義します
ArraySubType = UnmanagedType.LPStrはDLL側の文字セットにあわせましょう
Unicodeならば ArraySubType = UnmanagedType.LPWStr とします
コールバック関数の定義を
public static int onReceivedFiles2(string[] files, int n)
{
return 1;
}
といった具合にしてやれば 引数files配列は要素n個として認識されます
下記参考URLなども熟読してましょう
参考URL:http://msdn.microsoft.com/ja-jp/library/z6cfh6e6 …
No.1
- 回答日時:
この方法だと無理がありそうです
C++側からは messages_ ポインタと strngをいくつ返したかの int型をを渡す方が良いでしょう
アンマネージのC++側ではマネージコード側の配列をいくつに設定したのかを制御していません
typedef int (__stdcall *OnReceivedFilesProc )(char**, int);
で宣言
int ret_ = callback(messages_, sizeof(message_)/sizeof(message_[0]));
としてコールバックを呼び出す
デリゲートは
public delegate int StringArrayCallback(IntPtr ptr, int nVal);
と宣言
コールバック関数を
public static int onReceivedFiles(IntPtr ptr, int nVal)
{
IntPtr pptr;
string[] files = new string[nVal];
for( int n = 0; n < nval; n++ ) {
// スタックに積まれて来るのはポインタのみなので
pptr = Marshal.ReadIntPtr( ptr, n * 4 );
files[n] = Marshal.PtrToStringAuto( pptr );
}
return 1;
}
といった具合にすればよさそうです
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
int i, int i[1];
-
c言語
-
C#で構造体の配列を持った構造...
-
配列の要素数に変数を入れたい...
-
C言語 ファイルの指定された行...
-
C言語 数値の連続入力について
-
構造体を引数とする関数について
-
define で 配列
-
構造体のextern方法
-
C言語において、 配列要素をひ...
-
C#でのフィボナッチ数列
-
コンボボックスでデフォルト値...
-
C言語の配列のコピーについて
-
Cのエラー
-
std::vector 2次元配列の列方向...
-
Integer変数をカラにしたいので...
-
VB.NETでファイル名順にファイ...
-
配列で格納したものをmsgboxで...
-
VBAのプログラムで、DIAG = 1# ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
構造体のextern方法
-
配列の要素数に変数を入れたい...
-
C言語において、 配列要素をひ...
-
define で 配列
-
c言語
-
C#で構造体の配列を持った構造...
-
C言語 ファイルの指定された行...
-
c言語 構造体
-
コンボボックスでデフォルト値...
-
配列のアドレス部
-
MFCのCArrayを使った二次元配列
-
MFC - ダイアログボックスのPic...
-
C言語についてです 5人のテスト...
-
C言語から質問です。
-
AfxBeginThread の引数について
-
C言語の課題が出たのですが自力...
-
Cのエラー
-
int i, int i[1];
-
C#で配列が空かを判定するには?
おすすめ情報