2017-03-21 3 views
1

J'ai la fonction suivante, écrite dans le cadre d'une autre classe en C:Comment puis-je marshaler ce paramètre de tableau de caractères de C à une chaîne en C#?

int example(char *remoteServerName) 
{ 
    if (doSomething(job)) 
     return getError(job); 
    if (job->server != NULL) { 
     int length = strlen(jobPtr->server->name); // name is a char * of length 1025 
     remoteServerName = malloc (length * sizeof(char)); 
     strncpy(remoteServerName, jobPtr->server->name, length); 
    } 
    return 0; 
} 

Comment puis-je obtenir le remoteServerName retour de celui-ci? J'ai essayé ce qui suit:

[DllImport("example.dll")] 
public static extern int example(StringBuilder remoteServerName); 

var x = new StringBuilder(); 
example(x); 
Console.WriteLine(x.ToString()); 

Mais la chaîne est toujours vide.

+0

C ne supporte pas les classes. – Olaf

Répondre

4

Vous devez allouer un espace pour la chaîne à retourner au lieu de:.

var x = new StringBuilder(); 

fournissent une valeur de capacité:

var x = new StringBuilder(1024); 

Vous devez également supprimer votre appel à malloc. L'appelant alloue la mémoire. C'est le but de marshalling avec StringBuilder.

Vous n'utilisez pas correctement strncpy et vous ne parvenez pas à écrire un terminateur null. Vous pouvez passer la longueur du tampon comme celui-ci:

int example(char *remoteServerName) 
{ 
    if (doSomething(job)) 
     return getError(job); 
    if (job->server != NULL) { 
     // note that new StringBuilder(N) means a buffer of length N+1 is marshaled 
     strncpy(remoteServerName, jobPtr->server->name, 1025); 
    } 
    return 0; 
} 

Mais ce serait un peu inutile, avec tout le rembourrage zéro qui est implicite. Vraiment, strncpy est à côté de inutile et vous devriez utiliser une fonction différente à copier, comme cela a été discuté plusieurs fois auparavant ici. Je ne veux pas vraiment me laisser entraîner, parce que c'est un peu à l'écart de la question.

Il serait prudent de concevoir votre API pour permettre à l'appelant de passer également la longueur du tableau de caractères afin que l'appelé puisse s'assurer de ne pas dépasser le tampon, et ainsi vous n'avez pas besoin d'utiliser les constantes magiques comme le code ici fait.

+0

J'essaye ceci mais il y a quelque chose d'autre qui ne fonctionne pas ici, parce que c'est encore vide. Je peux vérifier que la variable 'int length' a une valeur de' 9'. – Alexandru

+0

Oui, il y avait d'autres erreurs dans votre code que je n'ai pas vues à l'origine. Pardon. Maintenant réparé, j'espère. –

+1

@Alexandru Pour un exemple de la manière dont l'API Windows gère le reporting de la taille de la mémoire tampon, voir [GetWindowText()] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633520 (v = vs.85) .aspx) et [GetWindowTextLength()] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633521 (v = vs.85) .aspx) –