0

MimeTex.dllC++/CLI プロジェクトの混合モードで使用しようとしています。次の方法でdllを含めます。 #pragma comment(lib,"MimeTex.dll")

そして、私はこのメソッドを呼び出そうとしました: CreateGifFromEq("expression","path");

しかし、コンパイラは CreateGifFromEq() メソッドを知らないと通知します。

MimeTex.dllC++ での使用方法に関する Web のリソースは見つかりませんでした 。Pinvok のこのリンクで、C# で使用する方法を見つけました。

[System.Security.SuppressUnmanagedCodeSecurity()]
internal class NativeMethods
{
    private NativeMethods()
    { //all methods in this class would be static
    }

    [System.Runtime.InteropServices.DllImport("MimeTex.dll")]
    internal static extern int CreateGifFromEq(string expr, string fileName);

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    internal extern static IntPtr GetModuleHandle(string lpModuleName);

    [System.Runtime.InteropServices.DllImport("kernel32.dll")]
    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    internal extern static bool FreeLibrary(IntPtr hLibModule);
}

そしてそれを次のように呼び出します:

NativeMethods.CreateGifFromEq(equation, tempGifFilePath);

C++/CLI の混合モードで Pinvok なしで呼び出すにはどうすればよいですか?

4

3 に答える 3

1

確かにあなたは書くつもりでした:

#pragma comment(lib,"MimeTex.lib")

つまり、.dll ではなく、.lib ファイルをリンカーに渡します。DLL をコンパイルすると、.lib ファイルが生成されます。

しかし、それはあなたの差し迫った問題ではありません。コンパイラには の宣言がありませんCreateGifFromEq。これは、C++ コードにライブラリのヘッダー ファイルが含まれていないためです。そうすることで問題が解決するはずです。

その 1 つの関数だけが必要な場合は、C++ コードで宣言するのは簡単です。

__declspec(dllimport) extern int CreateGifFromEq(char *expr, char *fileName);

extern "C"おそらく、それもブロックでラップする必要があります。

実際、ライブラリを調べたところ、ソースと共に提供されるヘッダー ファイルは、ライブラリに存在するにもかかわらず、その関数を宣言していません。

于 2013-03-28T16:47:33.467 に答える
1

C++/CLI では、C# と同様に P/Invoke を使用できます。

P/Invoke を使用したくない場合は、LoadLibraryで DLL をロードし、 GetProcAddressで関数へのポインターを取得する方法もあります。


C++/CLI の C# コードに相当するものを次に示します。

using namespace System;
using namespace System::Runtime::InteropServices;

private ref class NativeMethods abstract sealed
{
internal:
    [DllImport("MimeTex.dll")]
    static int CreateGifFromEq(String^ expr, String^ fileName);

    [DllImport("kernel32.dll")]
    static IntPtr GetModuleHandle(String^ lpModuleName);

    [DllImport("kernel32.dll")]
    [returnvalue: MarshalAs(UnmanagedType::Bool)]
    static bool FreeLibrary(IntPtr hLibModule);
};

ご覧のとおり、いくつかのマイナーな構文変更を除いて、C# コードとほとんど同じです。

LoadLibrary と GetProcAddress を使用する方法は次のとおりです (マーシャリングを必要としないという利点がありますが、これは C++ では不要です)。

HMODULE hModule = LoadLibrary(L"MimeTex.dll");
int (*fpCreateGifFromEq)(WCHAR*, WCHAR*) = GetProcAddress(hModule, "CreateGifFromEq");
(*fpCreateGifFromEq)(L"expression", L"filename");

GetModuleHandle と FreeLibrary についてはその必要はありません。これらは kernel32.dll からのものであるため、Windows.h をインクルードして通常どおり呼び出すことができるからです。

于 2013-03-28T16:49:14.400 に答える
0

物事を行うためのよりクリーンな方法があります:

C++/CLI プロジェクトを作成します。これは、C# と C++ の間のインターフェイスになります (これが C++/CLI の目的です)。

C# プロジェクトがこの新しいアセンブリへの参照を持つようにします。

新しい C++/CLI プロジェクト内で、コンパイラがプロジェクトをコンパイルするための mimetex .h ファイルを含むディレクトリと、リンカのための .lib/.dll を含むディレクトリを指すように、プロジェクト オプションを構成します。

C++/CLI 部分では、関数内に C++ を記述するだけです。これらは C# アセンブリに公開されますが、内部では通常どおり C++ 関数を呼び出すだけです。 (C++CLI チュートリアルをチェックして、文字列をネイティブ char または std::string に変換する方法を知る必要があります。私はそれを見なければならなかったことを覚えています。)*

C# の部分では、C++CLI プロジェクト アセンブリ公開関数を通常の C# 関数のように呼び出すだけで、ネイティブ コードが背後で呼び出されていることに気付かずに済みます。

于 2013-03-28T16:55:28.510 に答える