8

これが脳みそで簡単な質問であることを願っていますが、これは私の C++ に関する専門知識の欠如を示しています。私は C# プログラマーであり、過去に他の人の C++/C dll を使用して P/Invoke で広範な作業を行ってきました。ただし、今回はラッパー C++ dll (アンマネージ) を自分で作成することにし、C# からラッパー dll を呼び出しています。

私がすぐに直面している問題は、p/invoke で見つけられる C++ 関数を定義できないことです。これの構文が何であるかはわかりませんが、これまでに試したことは次のとおりです。

extern bool __cdecl TestFunc()
{
  return true;
}

もともと私はこれを持っていましたが、どちらも機能しませんでした:

bool TestFunc()
{
  return true;
}

そして、C# 側では、次のようにしています。

    public const string InterfaceLibrary = @"Plugins\TestDLL.dll";

    [DllImport( InterfaceLibrary, CallingConvention = CallingConvention.Cdecl,
        EntryPoint = "TestFunc" ), SuppressUnmanagedCodeSecurity]
    internal static extern bool TestFunc();

すべてがコンパイルされますが、この C# p/invoke 呼び出しを実行すると、System.EntryPointNotFoundException: Unable to find an entry point named 'TestFunc' in DLL 'Plugins\TestDLL.dll' が発生します。

確かに、これは構文を知らない C++ 側では信じられないほど単純なものに違いありません。

4

6 に答える 6

13

次のように、extern "C"と同様に使用する必要があります。__declspec(export)

extern "C" _declspec(dllexport)  bool TestFunc()
{
    return true;
}

詳細については、MSDN on Marshalling Typesを参照してください。

于 2009-10-07T20:21:52.917 に答える
7

リードの正解を拡張します。

PInvoke を介して C++ 関数を公開するときに発生する可能性のある別の問題は、無効な型を使用することです。PInvoke が実際にサポートできるのは、プリミティブ型と単純な古いデータ構造体/クラス型のマーシャリングのみです。

たとえば、TestFunc に次のシグネチャがあるとします。

void TestFunc(std::string input);

extern "C" を追加しても__declspec(dllexport)、C++ 関数を公開するには不十分です。代わりに、PInvoke と互換性のある型のみを公開し、メイン関数を呼び出すヘルパー関数を作成する必要があります。例えば

void TestFunc(const std::string& input) { ... }

extern "C" _declspec(dllexport)  void TestFuncWrapper(char* pInput) {
  std::string input(pInput);
  TestFunc(input);
}
于 2009-10-07T20:35:08.587 に答える
1

このようなことをしてください:

#define EXPORT extern "C" __declspec(dllexport)

次に、EXPORTキーワードを使用して、c++関数などの関数を宣言します。

BOOL getString(TCHAR* string, DWORD size);

になります

EXPORT BOOL getString(TCHAR* string, DWORD size);

次に楽しい部分:VSコンソールに移動して次のように入力します:

dumpbin /EXPORTS <PATH_TO_GENERATED_DLL>

簡単にエクスポートできるすべての関数の名前と序数が壊れているのがわかります。それなら、それらを呼び出すだけです。

于 2011-01-26T14:51:24.837 に答える
1

この関数を公開する必要がありますextern "C"。そうしないと、名前が壊れてしまいます。

于 2009-10-07T20:21:29.143 に答える
1

C++ コンパイラは、関数の名前を変更して、パラメーターと戻り値の型に関する情報を組み込みます。これはネームマングリングと呼ばれます。一方、C コンパイラは関数名をマングルしません。

以下を使用して、C++ コンパイラに C コンパイラとして動作するように指示できますextern "C"

extern "C" __declspec(dllexport) bool TestFunc { return true; }

P/Invoke を使用して C# から関数を呼び出すには、名前を壊してはなりません。したがって、実際に C 関数を C# にエクスポートできます。機能を C++ で実装する場合は、機能を実装する C++ 関数を呼び出すだけの C 関数を作成できます。

于 2009-10-07T20:24:22.790 に答える
0

Win32 プラットフォームと適切なビット (x86 または x64 など) ビルド オプションを使用してすべてのプロジェクトをビルドします。

于 2016-02-24T09:30:21.150 に答える