みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

MFC C++ と C++/CLI の文字列

VS2008です。

Library: NativeC++ with MFC -> DLL
  ↑↓
Wrapper: C++/CLI with .NET -> DLL
  ↑↓
Appli: VB.NET with .NET -> EXE

元々、ActiveXコントロール(非GUI利用)だったNativeC++で書かれたLibraryを
MFC DLLとしてビルドし、Wrapper 経由で Appli から使用できるよう
移植をしています。

Library から必要な関数を dllexport し、wrapper から参照し、
wrapper を Appli が参照して、使用できるようにしました。
int型を引数に取り、結果として返す関数は期待どおり動作しますが、
文字列だと上手く行きません。

Wrapper/Appli は System.CString で統一したいのですが、
Library ではどのような型として宣言すれば文字列のやり取りができるでしょうか。
( 引数・戻値の両者 )

CString wchar_t* char* System.String ALT::CStringT basic_string _bstr_t CComBSTR
LPCTSTR LPTSTR PCTSTR PTSTR LPCWSTR LPWSTR PCWSTR PWSTR BSTR…

なお、Library で下記のようにエクスポートし
__declspec(dllexport) BSTR test(LPCTSTR data);
wrapper で
BSTR hoge(LPCTSTR value){ return test(value); }
と宣言すると、wrapperのビルドで下記のエラーが表示されます。

エラー1error LNK2028: 未解決のトークン (0A000B39)
"wchar_t * __cdecl test(wchar_t const *)" (?test@@$$FYAPA_WPB_W@Z) が
関数 "public: wchar_t * __clrcall wrap::hoge(wchar_t const *)"
(?hoge@C3dlib@@$$FQ$AAMPA_WPB_W@Z) で参照されました。wrapper.objwrapper

エラー2error LNK2019: 未解決の外部シンボル
"wchar_t * __cdecl test(wchar_t const *)" (?test@@$$FYAPA_WPB_W@Z) が
関数 "public: wchar_t * __clrcall wrap::hoge(wchar_t const *)"
(?hoge@C3dlib@@$$FQ$AAMPA_WPB_W@Z) で参照されました。wrapper.objwrapper

エラー3fatal error LNK1120: 外部参照 2 が未解決です。

投稿日時 - 2011-10-26 15:25:55

QNo.7095567

すぐに回答ほしいです

質問者が選んだベストアンサー

Library の DLL に対して
Dumpbin /exports XXXXX.dll
とするとどうなりますか?

投稿日時 - 2011-10-28 15:19:41

お礼

ご回答ありがとうございます。根本的な解決には至りませんが、 急務だった為、以下のようなメソッドを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);
}

投稿日時 - 2011-10-31 12:57:50

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

すみません、エラーメッセージの __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 が更新されていないということはありませんか?

投稿日時 - 2011-10-27 12:38:55

補足

確認をしたところ、ちゃんと更新されているようです。質問文の「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もちゃんと参照できているはずですが、どうしたものか…。

投稿日時 - 2011-10-28 11:12:34

ANo.1

C++/CLI 側 ( wrapper 側 ) ではデフォルトで __clrcall になるので
extern BSTR __cdecl test( LPCTSTR value );
のように宣言しないとダメみたいですね。

投稿日時 - 2011-10-26 22:45:24

補足

ふむふむ。Library、Wrapperの両方とも、念の為に/Gdオプション付きでコンパイルしてました。

Library: __declspec(dllexport) extern BSTR __cdecl test(LPCTSTR value);
Wrapper: BSTR hoge(LPCTSTR value){ return test(value); }

上記のように変更してみたところ、次のエラーが表示されました。

エラー14error 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) で参照されました。
エラー15error 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) で参照されました。
エラー16fatal error LNK1120: 外部参照 2 が未解決です。

投稿日時 - 2011-10-27 09:58:12

あなたにオススメの質問