- ベストアンサー
MFC C++とC++/CLIの文字列に関する質問
- MFC C++とC++/CLIを使用して文字列のやり取りをする際の問題について質問しています。
- NativeC++で書かれたLibraryをMFC DLLとしてビルドし、Wrapper経由でAppliから使用するために移植しています。
- int型の引数を受け取り、結果を返す関数は正常に動作しますが、文字列のやり取りがうまくいかない問題が発生しています。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
Library の DLL に対して Dumpbin /exports XXXXX.dll とするとどうなりますか?
その他の回答 (2)
- tsukasa-12r
- ベストアンサー率65% (358/549)
すみません、エラーメッセージの __cdecl を __clrcall と見間違えてしまっていたため、 とんちんかんな回答になってしまいました。 wrapper 側から __cdecl で呼ぼうとしていたんですね。 試しに Visual Studio 2008 で C/C++ Native DLL で __declspec(dllexport) BSTR test( LPCTSTR data ) { return ( BSTR )data; } とし ( /Gd )、C++/CLI Windows フォームアプリケーションで extern BSTR __cdecl test( LPCTSTR value ); と宣言して BSTR bstr = test(_T("Test")); のようにすると、ビルドも実行もエラーなく正常に実行できました。 int 型の関数は正常に実行出来ているということは、.lib が正しく指定されていないというわけでもなさそうですし、不思議ですね・・・。 Wrapper のプロジェクトで参照している .lib が更新されていないということはありませんか?
補足
確認をしたところ、ちゃんと更新されているようです。質問文の「int型を引数に取り、結果として返す関数は期待どおり動作」は、具体的には int add(int a, int b){ return a+b; } でした。文字列では上手くいかないので、とりあえず、他の型は?と考えて試してみたところ、float型引数を6個取りintを返す int piyo(float x., float y, float z, float vx, float vy, float vz) でも、同じ「未解決のトークン/シンボル」となりました。型も名前も合っていて、libもちゃんと参照できているはずですが、どうしたものか…。
- tsukasa-12r
- ベストアンサー率65% (358/549)
C++/CLI 側 ( wrapper 側 ) ではデフォルトで __clrcall になるので extern BSTR __cdecl test( LPCTSTR value ); のように宣言しないとダメみたいですね。
補足
ふむふむ。Library、Wrapperの両方とも、念の為に/Gdオプション付きでコンパイルしてました。 Library: __declspec(dllexport) extern BSTR __cdecl test(LPCTSTR value); Wrapper: BSTR hoge(LPCTSTR value){ return test(value); } 上記のように変更してみたところ、次のエラーが表示されました。 エラー 14 error LNK2028: 未解決のトークン (0A000B5B) "wchar_t * __cdecl test(wchar_t const *)" (?test@@$$FYAPA_WPB_W@Z) が関数 "public: wchar_t * __clrcall C3dlib::hoge(wchar_t const *)" (?hoge@C3dlib@@$$FQ$AAMPA_WPB_W@Z) で参照されました。 エラー 15 error LNK2019: 未解決の外部シンボル "wchar_t * __cdecl test(wchar_t const *)" (?test@@$$FYAPA_WPB_W@Z) が関数 "public: wchar_t * __clrcall C3dlib::hoge(wchar_t const *)" (?hoge@C3dlib@@$$FQ$AAMPA_WPB_W@Z) で参照されました。 エラー 16 fatal error LNK1120: 外部参照 2 が未解決です。
お礼
ご回答ありがとうございます。根本的な解決には至りませんが、 急務だった為、以下のようなメソッドをwrapper側に実装し、appliとlibraryの間を取り持つようにしました。 /* System::String 型を char* 型にする */ void string2charpt(System::String^ str, char* c) { cli::array<wchar_t>^ wch = str->ToCharArray(); *c = '\0'; for ( int i ; i < wch->Length ; i++ ){ *(c+i) = wch[i]; *(c+i+1) = '\0'; } } void charpt2string(char* c, System::String^ str) { int i; str = System::String::Empty; for ( i = 0; *(c+i) != '\0'; i++ ) str += *(c+i); }