MFC C++とC++/CLIの文字列に関する質問

このQ&Aのポイント
  • MFC C++とC++/CLIを使用して文字列のやり取りをする際の問題について質問しています。
  • NativeC++で書かれたLibraryをMFC DLLとしてビルドし、Wrapper経由でAppliから使用するために移植しています。
  • int型の引数を受け取り、結果を返す関数は正常に動作しますが、文字列のやり取りがうまくいかない問題が発生しています。
回答を見る
  • ベストアンサー

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のビルドで下記のエラーが表示されます。 エラー 1 error 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.obj wrapper エラー 2 error 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.obj wrapper エラー 3 fatal error LNK1120: 外部参照 2 が未解決です。

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

  • ベストアンサー
回答No.3

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

sumire_kanou
質問者

お礼

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

その他の回答 (2)

回答No.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 が更新されていないということはありませんか?

sumire_kanou
質問者

補足

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

回答No.1

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

sumire_kanou
質問者

補足

ふむふむ。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 が未解決です。

関連するQ&A

  • wsprintfのエラーについて

    Visual C++を使ってC++,Win32APIでプログラムしています。 ウィンドウ上に変数の値を表示したいのですが、うまくできません。 wsprintfを使うと以下のようなエラーがでてしまいます。 1>time.obj : error LNK2020: 未解決のトークン (0A000015) "extern "C" int __cdecl wsprintfW(wchar_t *,wchar_t const *,...)" (?wsprintfW@@$$J0YAHPA_WPB_WZZ) 1>time.obj : error LNK2020: 未解決のトークン (0A000016) "extern "C" int __cdecl wsprintfW(wchar_t *,wchar_t const *,...)" (?wsprintfW@@$$J0YAHPA_WPB_WZZ) 1>time.obj : error LNK2001: 外部シンボル ""extern "C" int __cdecl wsprintfW(wchar_t *,wchar_t const *,...)" (?wsprintfW@@$$J0YAHPA_WPB_WZZ)" は未解決です。 1>C:\Documents and Settings\home\My Documents\Visual Studio 2005\Projects\time\Debug\time.exe : fatal error LNK1120: 外部参照 3 が未解決です。 どのようにすればよいのでしょうか?または、他のやり方があるのでしょうか? お願いします。

  • C++STLについての質問です。

    C++STLについての質問です。 Visual C++ 2008 Express Edition を使用してDirectXアプリケーションを 作成しています。 その折、std::listテンプレートを使用する機会があったのですが、このリストを 使用しますと、 リンクしています... LINK : warning LNK4098: defaultlib 'LIBCMT' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。 libcpmtd.lib(stdthrow.obj) : error LNK2019: 未解決の外部シンボル __CrtDbgReportW が関数 "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z) で参照されました。 libcpmtd.lib(xdebug.obj) : error LNK2019: 未解決の外部シンボル __malloc_dbg が関数 "void * __cdecl operator new(unsigned int,struct std::_DebugHeapTag_t const &,char *,int)" (??2@YAPAXIABU_DebugHeapTag_t@std@@PADH@Z) で参照されました。 libcpmtd.lib(xdebug.obj) : error LNK2019: 未解決の外部シンボル __free_dbg が関数 "void __cdecl operator delete(void *,struct std::_DebugHeapTag_t const &,char *,int)" (??3@YAXPAXABU_DebugHeapTag_t@std@@PADH@Z) で参照されました。 fatal error LNK1120: 外部参照 3 が未解決です。 とのエラーが吐かれます。 ネットで検索すると、ソリューション構成をDebugからReleaseにすれば良いとの記述が ありましたので、実行してみました。しかし、 リンクしています... error LNK2001: 外部シンボル "_D3DXCreateTextureFromFileExW@56" は未解決です。 error LNK2001: 外部シンボル "_D3DXCreateSprite@8" は未解決です。 error LNK2001: 外部シンボル "_D3DXGetImageInfoFromFileW@8" は未解決です。 error LNK2001: 外部シンボル "_Direct3DCreate9@4" は未解決です。 fatal error LNK1120: 外部参照 4 が未解決です とのエラーが吐かれてしまいました。 尚、コード生成モードは、マルチスレッド(/MT)で作成しています。 どなたか、この問題を解決する方法をご存知ないでしょうか? よろしくお願いします。

  • C++でdllの呼び出しについて

    使用環境はVisualStudio2008、WindowsXPです。 http://www.voidtools.com/Everything-SDK.zip こちらのSDKに添付されているdllを呼び出したいと思います。 dll、lib、ヘッダーファイルをプロジェクトと同じフォルダに入れて以下のようなコードを書いてみたのですが、リンカエラーになりました。 #pragma comment(lib, "everything.lib") void __stdcall Everything_SetSearch(LPCTSTR lpString); void main(void){ Everything_SetSearch(L"ああ"); } ビルドエラーの内容 error LNK2019: 未解決の外部シンボル "void __stdcall Everything_SetSearch(wchar_t const *)" (?Everything_SetSearch@@YGXPB_W@Z) が関数 _main で参照されました。 fatal error LNK1120: 外部参照 1 が未解決です。 何か初歩的なミスをしている気もしますが、突っ込みなどなど回答の方よろしくお願いします。

  • VC++2008でのサンプルプログラムのビルド

    VC++2008を使用してWin32APIを使ったプログラムを動かしたいと思っている者です。 これまでC言語については多少学んできましたがC++を使用するのは初めてです。 まずはサンプルプログラムを動かそうと思い以下のソースを入力しました。 #include <windows.h> #include <tchar.h> int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int showCmd) { MessageBox( NULL, _T("Hello World"), _T("メッセージ"), MB_OK ); return 0; } そしてこれをビルドしてみたところエラーメッセージがでてしまいうまくビルドできませんでした。 参考にしているHPはVC++2008での作業を推奨していたので、動作環境の違いなどではないと思うのですが… 初期設定等の問題になるのでしょうか?解決策があれば教えていただきたいです。 以下が表示されるエラーメッセージです。 1>1.obj : error LNK2028: 未解決のトークン (0A000044) "extern "C" int __stdcall MessageBoxW(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBoxW@@$$J216YGHPAUHWND__@@PB_W1I@Z) が関数 "extern "C" int __cdecl MessageBox(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBox@@$$J0YAHPAUHWND__@@PB_W1I@Z) で参照されました。 1>1.obj : error LNK2019: 未解決の外部シンボル "extern "C" int __stdcall MessageBoxW(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBoxW@@$$J216YGHPAUHWND__@@PB_W1I@Z) が関数 "extern "C" int __cdecl MessageBox(struct HWND__ *,wchar_t const *,wchar_t const *,unsigned int)" (?MessageBox@@$$J0YAHPAUHWND__@@PB_W1I@Z) で参照されました。 1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\1\Debug\1.exe : fatal error LNK1120: 外部参照 2 が未解決です。

  • 定義した文字列を wchar_t 系の関数へ

    こんにちは。 VisualStudioでマルチバイト文字セットを使用する設定のプロジェクトで、下記のように定義された文字列を wchar_t をパラメータとする関数にセットするにはどのようにすればよろしいのでしょうか? #define _FOO "foo" void funcA( const char* const szValue ) { } void funcW( const wchar_t* const szValue ) { } void test( void ) { funcA( TEXT( FOO )) ; ← ok。 funcW( TEXT( FOO )) ; ← エラー。 } UNICODE文字セットを使用する設定のプロジェクトならば問題ないのですが、マルチバイト設定ですとエラーになってしまいます。UNICODE、マルチバイト両方にプロジェクトに対応できるにはどうきじゅつすればよろしいのでしょうか。

  • C++/CLIでfstream(.NET 3.5)

    過去の資産にアクセスするためにC#から使うクラスライブラリをC++/CLIで作成しています。 当初は.NET Framework 4.5で作成していたのですが、Windows7でFrameworkを追加するのが面倒くさいという事で、3.5でプロジェクトを起こし直してコンパイルしました。 そうしたところ、大量のリンクエラーが発生しました。 --抜粋(下記を含め、合計18行のエラー) VCMRTD.lib(locale0_implib.obj) : error LNK2034: metadata は、COFF シンボル テーブルと整合しません: LINK : error LNK2034: metadata は、COFF シンボル テーブルと整合しません MSVCMRTD.lib(locale0_implib.obj) : error LNK2020: 未解決のトークン (0A0000A1) "extern "C" double __cdecl _hypot(double,double)" (?_hypot@@$$J0YANNN@Z) -- 調査した結果、fstream関連を定義するとこの症状が出る事がわかりました。 そこで、単純に以下のプロジェクトを作成したところ、同じ現象が発生しました。 1..NET Framework 3.5でCLRクラスライブラリのプロジェクトを作成する(ここではTESTプロジェクト) 2.作成されたテンプレートの「TEST.h」に関数を追加する -----(TEST.h) // TEST.h #pragma once #include <fstream> using namespace System; namespace TEST { public ref class Class1 { void test() { std::fstream f; } }; } ---- 3.コンパイル → リンクエラー 標準関数はいくつか使っているのですが、fstream系だけがダメなようです。 (sstreamはOKでした) これに関して、何か対策方法はないものでしょうか。 情報があればお教え下さい。 よろしくお願いいたします。 開発環境: Windows 8.1 VisualStudio 2013 Pro

  • C++Builder 2009 テキストボックスの文字列取得

    Editは、テキストボックスです。 Editには、"12345"の半角文字列が入っています。 これを、C言語の文字列として取得しようとしました。 このときのソースコードは、次の通り。 -------- char *ptr1 = new char[Edit->Text.Length()+1]; //独自領域にセーブ strcpy(ptr1, Edit->Text.c_str()); //ptr1にアドレスをコピー -------- このstrcpyの行で、エラーが出てしまい、対処に困っています。     ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ E2034 'wchar_t *' 型は 'const char *' 型に変換できない E2342 パラメータ '__src' は const char * 型として定義されているので wchar_t * は渡せない -------- Edit->Textで取得した文字列を、"12345\0"といった具合で処理をしたいのですが、どのようにしたらいいのでしょうか? 追記 「C++Builder 2009」以前のバージョンでは、難なく取得できていた。 同じソースコードなのに、何故かエラーになる。

  • VC++で正常にコンパイルできません(マイクロソフトのサンプルなんですが)

    こんにちは。 VC++の勉強を兼ねてマイクロソフトのサイトから色々なサンプルを入手し、コンパイルしているのですが、下記のサンプルはエラーがでてしまいます。 リンクのエラーみたいなのですが、どのように解決すれば良いか、ご存知の方がいらっしゃいましたら教えていただけないでしょうか? ちなみに下記のサンプルをtest.cppと名前を付けて保存し、コマンドプロンプトで下記の通り実行しています。 cl /EHsc test.cpp ■エラーがでるサンプル http://msdn.microsoft.com/library/en-us/wmisdk/wmi/example__getting_wmi_data_from_the_local_computer.asp タイトル:Example: Getting WMI Data From the Local Computer ---エラー内容 ここから▼--- C:\VS2005>cl /EHsc test.cpp Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. test.cpp Microsoft (R) Incremental Linker Version 8.00.50727.42 Copyright (C) Microsoft Corporation. All rights reserved. /out:test.exe test.obj test.obj : error LNK2019: 未解決の外部シンボル "wchar_t * __stdcall _com_util::C onvertStringToBSTR(char const *)" (?ConvertStringToBSTR@_com_util@@YGPA_WPBD@Z) が関数 "public: __thiscall _bstr_t::Data_t::Data_t(char const *)" (??0Data_t@_bs tr_t@@QAE@PBD@Z) で参照されました。 test.exe : fatal error LNK1120: 外部参照 1 が未解決です。 ---エラー内容 ここまで▲--- ■利用環境 WindowsXP HomeEdition SP2 Microsoft Visual C++2005 Express Edition Windows&reg; Server 2003 SP1 Platform SDK 足りない情報等がございましたら、ご指摘いただけると幸いです。

  • error C2664: 'LPCTSTR' に変換できません。

    error C2664: 'LPCTSTR' に変換できません。 はじめて質問します.よろしくお願いします. VisualStudio2008を使っています. カウンタボードのオープンの処理で,付属ライブラリの関数を用いて BOOL DeviceOpen(){ /* デバイス名"FBIPENC1"のオープン*/ hDeviceHandleCounter = PencOpen("FBIPENC1", PENC_FLAG_NORMAL); if (hDeviceHandleCounter == INVALID_HANDLE_VALUE) return FALSE; return TRUE; } とすると, error C2664: 'PencOpen' : 1 番目の引数を 'const char [9]' から 'LPCTSTR' に変換できません。(新しい機能 ; ヘルプを参照) というエラーが出てきてしまいます.このエラーを回避するにはどのようにしたらよいでしょうか?よろしくお願いします.

  • VC++2005で、CString型に16進文字列を入れたいのですが・・

    VC++2005で、CString型に16進文字列を入れたいのですが・・・ 次のようなエラーが出ます。 void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)' : 1 番目の引数を 'const char [5]' から 'const wchar_t *' に変換できません。 プログラムは次の通りです。 CString strBuff; CString strWork; TCHAR tszBuff[80]; UINT unLength; UINT un1; unLength = 5; strBuff = "12345"; _tcscpy(tszBuff, strBuff); strWork = ""; for(un1 = 0; un1 < unLength; un1++) { strWork = strWork + strBuff.Format("%02x", tszBuff[un1]); ←ここにエラーがあると言われています。 } 結果は、strWorkに、"3132333435"となるようにしたい! ネットで探したら、 >UNICODEを使われているのだと思われます。 >T("")マクロを使ってワイドキャラクタに変換するように指示すれば動くと思います。 とあったので、 strWork = strWork + strBuff.Format(_T("%02x"), tszBuff[un1]); としてみたのですが、 二項演算子 '+' : 型 'void' の右オペランドを扱う演算子が見つかりません (または変換できません)。 というエラーが表示されました。 VC++6.0を半年かじり、今日、初めてVC++2005に触った程度の初心者です。 どなたか助言を頂ければ幸いです。 環境  Windows XP Pro SP3  Visual C++ 2005(MFC) 以上、よろしくお願いします。

専門家に質問してみよう