|
カテゴリ:C#
【環境】
OS:Windows 7 64bit VS:Visual Studio 2008 SP1 言語:C++,C# C#から,C++(32bit)で作成したDLLを呼び出し 【エラー】 C#のプログラムを実行したところ,C++の関数を呼び出す部分で下記のエラー発生。 ![]() 呼び出し部分のコードはこちら。 C#:あるクラスの中の1関数 private string getName() { string name = DllWrapper.dllGetName(); return name; } C#:DLLラッパークラス namespace DllWrapperSpace { public class DllWrapper { [DllImport("dllTest.dll")] public static extern string dllGetName(); } } * dllTest.dll:C++のDLLの名前 C++:クラス class TestDll { private: char _name[1024]; public: char* getName() { return _name; } }; C++:DLL出力用のコード TestDll test; extern "C" { __declspec(dllexport) char* WINAPI dllGetName() { return test.getName(); } } 【原因】 C++のDLL関数の戻り値char* を,C#でstring として宣言したことが原因 C#では,戻り値をstringとして宣言した場合,マーシャリングにより自動的にC++のchar*が参照しているメモリを解放するとのこと。 おそろしや・・・ 相互運用マーシャリング 【対策】 C#の戻り値をstringからIntPtrへ。 IntPtrをPtrToStringAnsiでstringへ変換。 ちなみに,PtrToStringAutoでは文字化け。 OSが64bitだからか!?,AutoにするとC++からUnicodeで文字列を受け取っていると勘違いするらしい。 呼び出し部分のコードはこちら。 C#:あるクラスの中の1関数 private string getName() { IntPtr namePtr = DllWrapper.dllGetName(); string name = Marshal.PtrToStringAnsi(namePtr); return name; } C#:DLLラッパークラス namespace DllWrapperSpace { public class DllWrapper { [DllImport("dllTest.dll")] public static extern IntPtr dllGetName(); } } これで解決♪ 【おまけ】 今回のコードでは,戻り値として文字列を受け取ったが,引数として文字列を受け取ることも可能。 その場合には,C++の引数はchar*,C#の引数はStringBuilderとすればOK。 お気に入りの記事を「いいね!」で応援しよう
最終更新日
2010年02月10日 17時35分31秒
コメント(0) | コメントを書く
[C#] カテゴリの最新記事
|