web-dev-qa-db-fra.com

"Impossible de trouver un point d'entrée nommé [fonction] dans une dll" (conversion de type c ++ en c #)

J'ai une dll qui provient d'un tiers, qui a été écrite en C++. Voici quelques informations provenant de la documentation de la dll:

//start documentation

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

Description: Structure de données permettant de recevoir le résultat de la fonction. Tous les résultats de la fonction seront Enregistrés au format Unicode (UTF-8).

Méthode:

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

Contribution:

char * imgPath

chemin complet de l’emplacement de l’image pour que cette fonction puisse reconnaître

RECO_DATA * o_data

objet de données pour la réception de la fonction résultat. Renvoi de fonction: Vrai si Réussite, sinon faux retournera.

//end documentation

J'essaie d'appeler le recoCHN_P_Name à partir de mon application C #. À cette fin, je suis venu avec ce code:

Le code pour importer la 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);
}

Le code pour appeler la fonction:

            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);

Et l'erreur que j'obtiens est "" Impossible de trouver un point d'entrée nommé 'recoCHN_P_Name' dans DLL 'cnOCRsdk.dll'. " Je soupçonne que Je rencontre une erreur lors de la conversion d'un type de C++ en C #, mais où exactement ...?

20
Evgeny

D'abord, assurez-vous que la fonction est réellement exportée:

Dans l'invite de commandes Visual Studio, utilisez dumpbin /exports whatever.dll

32
i_am_jorf

C # ne prend pas en charge le changement de nom C++ et vous devez soit déclarer les fonctions C++ avec

extern "C" {...}

(peut ne pas être une option s’ils proviennent d’un tiers), ou appelez directement le nom mutilé si vous pouvez le faire fonctionner. Il peut être plus facile de demander à la tierce partie de fournir une interface non mutilée à la fonctionnalité.

20
paxdiablo

Résolu - au moins au point où le programme ne se casse pas et me renvoie réellement une valeur booléenne.

La clé, je suppose, était de spécifier le point d’entrée sous le nom «mutilé»

    [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);

Après cela, j'ai eu d'autres erreurs mais le «incapable de trouver le point d'entrée» est parti.

15
Evgeny

J'écrirais un wrapper en utilisant C++/CLI. Cet encapsuleur pourra inclure les fichiers .h et un lien vers les fichiers .lib que vous avez obtenus du fournisseur tiers. Ensuite, il est à la fois facile et sûr d’écrire une interface gérée pour votre programme C #.

3
Dan Byström

J'ai résolu le même problème dans ces étapes:

étape 1) Si vous programmez votre DLL personnalisé en C++ à l'aide de Visual studio, dans la page de propriétés de votre projet, définissez le paramètre Common Language Runtime Support (/clr)parameter sur Common Language Runtime Support (/clr)

étape 2) Pour utiliser la décélération dans le fichier .h, utilisez le mot clé __declspec(dllexport) comme ci-dessous:

__declspec(dllexport) double Sum(int a,int b);

étape 3) Créez et exportez le fichier DLL, puis utilisez le logiciel Dependency Walker pour obtenir votre fonction EntryPoint .

step4) Import DLL fichier Dans le projet C #, définissez EntryPoint et CallingConvention variable comme ci-dessous:

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

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

Vous pouvez essayer d’utiliser le nom non mélangé en spécifiant une convention Calling dans le fichier DllImport.

0
evilfred

Correct EntryPoint string pourrait être trouvé dans le fichier ".lib" fourni avec la dll principale non gérée.

0
uzrgm