2 votes

Maréchalage d'une .dll native en C# avec des pointeurs multiples

Avoir le code suivant en C++ :

  • nConId est l'identifiant de la connexion
  • pParName le nom du paramètre
  • pSubName le nom du sous-Paramètre (le cas échéant)
  • pValue_out un pointeur vers un tableau de caractères de longueur FCL_PAR_VALUE_LENGH
  • nValueSize la taille réelle du vecteur pValue_out (au moins FCL_PAR_VALUE_LENGH)
extern "C" MY_API int ReadParameter(const ConnectionId_T nConId, const char* pParName,
    const char *pSubName, char *pValue_out, const int nValueSize );

Mon essai est :

[DllImport("mydll.dll", CharSet = CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
public static extern int ReadParameter(ConnectionId_T pConId, IntPtr pParName,
    ref IntPtr pSubName, ref IntPtr[] pValue_out, int nValueSize);

J'utilise le code suivant pour appeler cette fonction :

# nConId is returned from another function and the his value is 0

public const int FCL_PAR_VALUE_LENGH = 128; 

string param_string = "AUXF";
IntPtr pParName = (IntPtr)Marshal.StringToHGlobalAnsi(param_string);

string subparam_string = "T";
IntPtr pSubName = (IntPtr)Marshal.StringToHGlobalAnsi(subparam_string);

IntPtr[] aParValue = new IntPtr[FCL_PAR_VALUE_LENGH]; 

int returnedValue = ReadParameter(nConId, pParName, ref pSubName,
    ref aParValue, FCL_PAR_VALUE_LENGH);

Lorsque j'exécute le code, j'obtiens un AccessViolationException donc je suppose qu'il y a quelque chose qui cloche dans mon appel.

Je me suis trompé de marshall ? Que dois-je changer dans le code pour obtenir une bonne réponse ?

PS : Je sais aussi que l'appel renvoie aussi quelque chose à aParValue .

3voto

Rotem Points 9668

Tu travailles trop dur avec ces char* s. Il est parfaitement légal (et encouragé) de rassembler un System.String pour l'entrée, et un StringBuilder pour la sortie.

[DllImport("mydll.dll", CharSet = CharSet.Ansi,CallingConvention=CallingConvention.Cdecl)]
public static extern int ReadParameter(
    ConnectionId_T pConId, 
    string pParName, 
    string pSubName,
    StringBuilder pValue_out,
    int nValueSize);

utilisation

const int sbLength = 256; //use a domain relevant value
StringBuilder sb = new StringBuilder(sbLength + 1); //for null character, hard to say if you need it without seeing the C++ code, but easier to just add it than find out.
int result = ReadParameter(conId, "paramname", "paramsubname", sb, sbLength);

Vous n'avez donné aucune indication sur le type sous-jacent de ConnectionId_T donc je suppose que vous avez exclu ce problème.

Référence MSDN

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X