Quelques points que je suis tombé sur tout en créant une enveloppe dll:
- je devais appeler une fonction de membre de la classe non géré. J'ai pris le temps de découvrir que je ne peux pas le faire en utilisant DllImport directement, mais je dois écrire un 'wrapper' moi-même.
- Dans l'emballage lui-même, il ne suffit pas non plus d'envelopper uniquement la fonction membre. Je dois être capable de créer un pointeur vers la classe C++, donc je dois exporter le pointeur vers le constructeur (au moins, c'est comme ça que je le comprends, peut-être que ce n'est pas exactement correct.). J'ai essayé juste d'exporter la fonction membre initialement, il a compilé mais a renvoyé "AccessViolationException" à l'exécution. Je suis resté là pendant un moment.
Par conséquent, mon emballage ressemble à ceci (comme le suggère using a class defined in a c++ dll in c# code):
public class __declspec(dllexport) Wrapper
{
public:
CcnOCRsdk* SDKCreate()
{
return new CcnOCRsdk();
}
bool CcnOCRsdk_HKID(CcnOCRsdk* pSDK, char *code, RECO_DATA *o_data)
{
return pSDK->convertHKID_Name(code, o_data);
}
void SDKDelete(CcnOCRsdk* pSDK)
{
delete pSDK;
}
};
__declspec (dllexport) sur les exportations de niveau de classe tous les membres publics de la classe. SDKCreate() renvoie un pointeur vers cette classe CcnOCRsdk à partir de la DLL non managée quelle fonction de membre je dois appeler. CcnOCRsdk_HKID appelle cette fonction de membre. Notez que le pointeur sur le CcnOCRsdk est passé.
Une fois le code généré dans la DLL, je dois utiliser le DUMPBIN pour savoir quels sont les points d'entrée "mutilés" pour la DLL d'encapsulation que j'ai écrite.
Pour mon emballage, les résultats se présentent comme suit
1 0 00001240 [email protected]@@[email protected]@@Z = [email protected][email protected]@@[email protected]@@Z ([T2M] public: class TSSL::Wrapper & __thiscall TSSL::Wrapper::operator=(class TSSL::Wrapper const &))
2 1 00001220 [email protected]@[email protected]@[email protected]@[email protected]@@Z = [email protected][email protected]@[email protected]@[email protected]@PAD[email protected]@@Z ([T2M] public: bool __thiscall TSSL::Wrapper::CcnOCRsdk_HKID(class CcnOCRsdk *,char *,struct RECO_DATA *))
3 2 00001200 [email protected]@[email protected]@[email protected]@XZ = [email protected]@[email protected]@[email protected]@XZ (public: class CcnOCRsdk * __thiscall TSSL::Wrapper::SDKCreate(void))
4 3 00001410 [email protected]@[email protected]@[email protected]@@Z = [email protected]@[email protected]@[email protected]@@Z (public: void __thiscall TSSL::Wrapper::SDKDelete(class CcnOCRsdk *))
Maintenant, je suis enfin prêt à utiliser mon emballage dans le C#.Lorsque je l'ai fait sans spécifier le point d'entrée exactement comme dans ma sortie de dumpbin, j'ai eu l'erreur 'Impossible de trouver le point d'entrée'.
[DllImport(@"TSSLWrapper.dll", EntryPoint = "[email protected]@[email protected]@[email protected]@XZ")]
public static extern IntPtr SDKCreate();
[DllImport(@"TSSLWrapper.dll", EntryPoint = "[email protected]@[email protected]@[email protected]@[email protected]@@Z")]
public static extern bool CcnOCRsdk_HKID(IntPtr ptr, string num, out RECO_DATA o_data);
Le RECO_DATA est défini comme JaredPar suggéré.
Et la dernière étape consiste à apprécier les résultats. D'abord, je dois appeler le constructeur de la classe, et ensuite passer le pointeur à l'appel réel à la fonction
RECO_DATA recoData = new cnOCRsdk.RECO_DATA();
string num = "262125355174";
IntPtr ptr = cnOCRsdk.SDKCreate();
bool res = cnOCRsdk.CcnOCRsdk_HKID(ptr, num, out recoData);
Mes res renvoie true, et j'obtenir les résultats que j'attendais à recoData.
Merci, j'ai finalement fait en sorte que tout fonctionne ensemble – Evgeny