web-dev-qa-db-ja.com

「[関数]という名前のエントリポイントがdllに見つかりません」(c ++からc#への型変換)

C++で記述されたサードパーティからのDLLがあります。以下は、dllのドキュメントからの情報です。

//start documentation

RECO_DATA{
wchar_t Surname[200];
wchar_t Firstname[200];
}

説明:関数の結果を受け取るためのデータ構造。すべての関数の結果はUnicode(UTF-8)として保存されます。

方法:

bool recoCHN_P_Name(char *imgPath,RECO_DATA *o_data);

入力:

char * imgPath

この関数が認識する画像の場所の完全なパス

RECO_DATA * o_data

関数結果を受け取るためのデータオブジェクト。関数の戻り値:成功の場合はtrue、それ以外の場合はfalseが返されます。

//end documentation

C#アプリケーションからrecoCHN_P_Nameを呼び出そうとしています。この目的のために、私はこのコードを思いつきました:

DLLをインポートするコード:

    public class cnOCRsdk
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct RECO_DATA{
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst=200)]
        public string FirstName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 200)]
        public string Surname;
        }

    [DllImport(@"cnOCRsdk.dll", EntryPoint="recoCHN_P_Name")]
    public static extern bool recoCHN_P_Name(byte[] imgPath, RECO_DATA o_data);
}

関数を呼び出すコード:

            cnOCRsdk.RECO_DATA recoData = new cnOCRsdk.RECO_DATA();

        string path = @"C:\WINDOWS\twain_32\twainrgb.bmp";

        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
        byte[] bytes = encoding.GetBytes(path);

        bool res = cnOCRsdk.recoCHN_P_Name(bytes, recoData);

そして、私が得ているエラーは、「DLL 'cnOCRsdk.dll'に 'recoCHN_P_Name'という名前のエントリポイントが見つかりません。」というエラーです。型をC++からC#に変換しますが、正確には...?

22
Evgeny

まず、関数が実際にエクスポートされていることを確認します。

Visual Studioコマンドプロンプトで、dumpbin /exports whatever.dllを使用します

34
i_am_jorf

C#はC++名のマングリングをサポートしていないため、C++関数を次のように宣言する必要があります

extern "C" {...}

(サードパーティ製の場合はオプションではない場合があります)、または正常に機能する場合は、マングルされた名前を直接呼び出します。サードパーティに機能のマングル化されていないインターフェイスを提供させるほうが簡単な場合があります。

23
paxdiablo

解決済み-少なくともプログラムが壊れず、実際にブール値を返すところまで。

キーは、おそらく、「破損した」名前としてエントリポイントを指定することでした

    [DllImport(@"cnOCRsdk.dll", EntryPoint="?recoCHN_P_Name@CcnOCRsdk@@QAE_NPADPAURECO_DATA@@@Z")]
    public static extern bool recoCHN_P_Name(ref string imgPath, ref RECO_DATA o_data);

その後、他のエラーが発生しましたが、「エントリポイントが見つかりません」と表示されなくなりました。

17
Evgeny

C++/CLIを使用してラッパーを記述します。このラッパーは、.hファイルをインクルードし、サードパーティベンダーから入手した.libファイルにリンクできます。次に、C#プログラム用のマネージインターフェイスを作成することは簡単かつ安全です。

3
Dan Byström

私はこれらのステップで同じ問題を解決しました:

手順1) Visual Studioを使用してC++でカスタムDLLをプログラムする場合、プロジェクトのプロパティページでCommon Language Runtime Support (/clr) parameterからCommon Language Runtime Support (/clr)へ。

ステップ2) _.h_ファイルで関数の減速を行うには、以下のような__declspec(dllexport)キーワードを使用します。

___declspec(dllexport) double Sum(int a,int b);
_

手順3)ビルドおよびエクスポートDLLファイル、次にDependency Walkerソフトウェアを使用して関数を取得EntryPoint

step4)インポートDLL file in the C#project and set EntryPoint and CallingConvention variable以下のように:

_[DllImport("custom.dll", EntryPoint = "?Sum@@YAXHHHHHHNNN@Z", CallingConvention = CallingConvention.Cdecl)]

    public static extern double Sum(int a,int b);
_
1
Hamid

DllImportでCallingConventionを指定するときに、符号化されていない名前を使用してみることができます

0
evilfred

正しいEntryPoint文字列は、メインの管理されていないdllに付属する「.lib」ファイルにあります。

0
uzrgm