Codage du code dll en C #

J’ai la signature de code C suivante dans une dll:

extern __declspec(dllexport) unsigned char * funct_name (int *w, int *h, char **enc, int len, unsigned char *text, int *lp, int *mp, int *ep) 

La fonction C peut modifier w, h, enc, lp, mp et ep (bien que les trois derniers puissent être nuls et ne feront rien.

J’utilise ce qui suit en C #

 [DllImport("iec16022ecc200.dll", EntryPoint = "iec16022ecc200", ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true, CallingConvention=CallingConvention.Cdecl)] static extern IntPtr CallEncode( [In,Out,MarshalAs(UnmanagedType.LPArray)] Int32[] width, [In,Out,MarshalAs(UnmanagedType.LPArray)] Int32[] height, [In,Out,MarshalAs(UnmanagedType.LPStr)] ref SsortingngBuilder encoding, int barcodeLen, [MarshalAs(UnmanagedType.LPStr)] SsortingngBuilder barcode, IntPtr lenp, IntPtr maxp, IntPtr eccp ); public void Foo (ssortingng textToEncode,out int width, out int height) { SsortingngBuilder text = new SsortingngBuilder(textToEncode); SsortingngBuilder encoding = new SsortingngBuilder(new ssortingng('a', text.Length)); Int32[] w = new Int32[1]; Int32[] h = new Int32[1]; ssortingng encodedStr = Marshal.PtrToSsortingngAnsi(CallEncode(w, h, ref encoding, text.Length, text, (IntPtr)0, (IntPtr)0, (IntPtr)0)); width = w[0]; height = h[0]; } 

Je reçois un SystemAccessViolation et je ne sais pas exactement quand mon problème se pose.

Ne transmettez pas une référence SsortingngBuilder à une méthode non managée qui prend un caractère *. Le contenu de SsortingngBuilder est unicode (wchar).

Au lieu de cela, remplacez le paramètre SsortingngBuilder par et le paramètre IntPtr et allouez un tampon de taille approprié à l’aide de Marshal.AllocHGlobal.

De plus, je ne pense pas que le fait de passer un SsortingngBuilder à du code non managé en utilisant “ref” soit supporté par le marshaller .Net.

Vous avez mentionné que le paramètre ‘char ** enc’ peut être modifié par l’appelé, ce qui pourrait entraîner l’erreur ‘SystemAccessViolation’. Un SsortingngBuilder peut être déréférencé et modifié par l’appelé, à condition qu’il ne dépasse pas la capacité de SsortingngBuilders.

SsortingngBuilder ne doit pas être passé par référence en utilisant out ou ref .

  //... [In,Out,MarshalAs(UnmanagedType.LPStr)] ref SsortingngBuilder encoding, //... 

Supprimez le mot clé ref du paramètre de encoding de type SsortingngBuilder . C’est ce qui cause probablement votre SystemAccessViolation .

J’essayais de passer une chaîne de C ++ à C # dans Unity. Et tout ce que j’ai eu était du charabia. Enfin, après avoir vu votre commentaire, @popcatalin, j’ai découvert la solution en utilisant AllocHGlobal de C # pour allouer de la mémoire à la chaîne.

Ceci est ma fonction C ++:

 extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API TestSsortingng(char* str, int len) { strcpy_s(str, len, "C++ Ssortingng!!! UniversalCpp"); return; } 

C’est en haut du script C # dans Unity:

 #if WRCCPP [DllImport("UniversalWRCCpp", CallingConvention = CallingConvention.Cdecl)] #else [DllImport("UniversalCpp", CallingConvention=CallingConvention.Cdecl)] #endif private static extern void TestSsortingng(IntPtr str, int len); private IntPtr myPtr = IntPtr.Zero; // Pointer to allocated memory 

Et voici mon script C # dans Unity appelant cette fonction:

 int sizeInBytes = 100; myPtr = Marshal.AllocHGlobal(new IntPtr(sizeInBytes)); TestSsortingng(myPtr, sizeInBytes); Debug.Log("ANSI " + Marshal.PtrToSsortingngAnsi(myPtr)); // This prints the correct format