2017-02-11 2 views
1

Avoir une fonction native qui renvoie une chaîne (comme char *) par paramètre, quelle serait la meilleure option entre pré-allouer le char * via le code managé et le passer par paramètre et allouer le char * à partir du code natif, puis le libérer de C#?Comment marshaler une chaîne de sortie du code natif

pourriez-vous m'expliquer pourquoi devrais-je utiliser l'un sur l'autre? Veuillez répondre uniquement s'il existe une raison spécifique de préférer une solution à l'autre. Si, au contraire, les deux solutions sont correctes, ma question peut être considérée comme une réponse. En prime, j'aimerais savoir comment je devrais allouer la variable char * de C# dans le premier cas (en utilisant la classe Marshal ou avec un simple nouveau ou avec un StringBuilder comme je le vois souvent dans d'autres réponses?) Et comment je devrais supprimer le pointeur si à la place je crée la variable char * à partir du code natif dans le second cas.

+0

Supprimer l'original s'il vous plaît. J'ai effectivement marqué pour supprimer hier, quelqu'un doit l'avoir restauré! Aussi l'original n'a pas eu de réponse, juste un commentaire – sebas

+0

@Flexo: La dupe a depuis été supprimée, et cette question, bien que quelque peu "douce", semble être sur le sujet et a une réponse décente. Pourriez-vous envisager de le rouvrir? –

Répondre

2

Il n'est généralement pas recommandé de renvoyer un char* à partir d'une fonction C et de s'attendre à ce qu'il soit désaffecté par l'appelant. L'appelant peut ne pas le faire (correctement ou pas du tout) et fuira ainsi la mémoire. Une façon courante pour éviter ce (tel qu'il est utilisé par OpenGL, OpenCL et d'autres bibliothèques que j'ai vu) est de déclarer le prototype comme:

int GetString(char* str, int* len);

avec une mise en œuvre comme ceci:

int GetString(char* str, int* len) 
{ 
    if (str == NULL) 
    { 
     len = internal_get_string_length(); 
     return 0; // No errors 
    } 
    else 
    { 
     if (len <= internal_get_string_length()) 
      return -1; // not enough space in str 
     char* internal_str = internal_get_string_ptr(); 
     strcpy(str, internal_str); 
     return 0; 
    } 
} 

La documentation indiquera alors que si str est NULL, la longueur de la chaîne à retourner est retournée en len. Sinon, le pointeur str devrait contenir autant de caractères que nécessaire. Pour l'utiliser, l'utilisateur appelle la fonction deux fois, une fois avec NULL pour str et un int pour len, puis à nouveau avec un tableau de char affecté aussi long que len. Un éventuel prototype pour P/Appel de ce type de fonction est:

// Declaration 
[DllImport("myDll.dll")] 
int GetString(StringBuilder sb, ref int len); 

// Usage 
int length; 
GetString(null, length); 
var sb = new StringBuilder(length); // Set capacity 
GetString(sb, length); 
Console.WriteLine(sb.ToString()); // Do stuff with C# string 

Hope that helps!

+0

un peu gênant mais au moins j'ai une meilleure compréhension maintenant – sebas