12
votes

Comment obtenir CHAR ** UTILISER C #?

J'ai besoin de passer une dispute à une fonction dllimportée dangereuse sous la forme de: xxx

Je suppose que c'est un tableau de chaînes. Cependant, lorsque j'essaie de faire ce qui suit, je ne peux pas convertir de la chaîne [] en erreur ** '. Comment puis-je aller pour que cela fonctionne? Merci. xxx

EDIT 1: La question a été marquée comme en double, mais en examinant la question duplicaté éventuelle, je ne vois toujours pas comment obtenir cela pour travailler.

EDIT 2: à la poursuite du Clafiry la question et paramètres requis. Il ressemble à vos paramètres Standard ArgC / Argv (Nombre de paramètres, puis les valeurs de paramètre). De la même manière que vous démarrerez Programme AC: Int Main (int Argc, Char ** argv); Pour ce problème particulier, je ne veux pas transmettre aucun argument (donc le nombre est de 0) .

EDIT 3: J'ai eu plus d'informations auprès du fournisseur de la bibliothèque tierce. Ici c'est:


19 commentaires

Char * Je sais comment faire, mais Char ** ...? Argh.


Convenu - la question est en fait concise. Je n'ai pas fait cela donc je ne peux pas répondre :)


Je pense que vous devez utiliser StringBuilder [] au lieu de chaîne []


Peut-être, mais il y a toujours le problème de la signature - Char ** n'est pas un StringBuilder.


@Lukstorms Je ne contrôle pas la fonction. C'est une DLL tiers.


Utiliser Ref to Un Char * pourrait le faire.


Que diriez-vous de ce lien: Stackoverflow. com / questions / 11572631 / ...


Qu'en est-il d'utiliser & args dans un contexte dangereux (où args est une chaîne )?


@Michaeldorgan La réponse à cette question a un lien apparemment utile (marshaling Char **) Mono -project.com/docs/advanced/pinvoke et c'est probablement là où je vais commencer à chercher si une solution plus facile ne se présente pas.


Notez que si c'est char in c, il ne sera pas char en C #; C Char est 1 octet mais C # Char est 2 octets


Les bowvotes sont parfaitement valables. Demander comment appeler une fonction non gérée sans spécification de cette fonction non gérée est inutile. Le type est char ** . Amende. Mais quelles sont les sémantiques?


Je pense que cela manque des informations; Combien de chaînes espérez-vous être ajoutées à la matrice? Sont-ils terminés nuls ou des chaînes de longueur fixe?


@DavidHeffernan j'ai mis à jour la question avec les informations pertinentes.


@Meirionhughes question mise à jour.


Non tu ne l'as pas fait. Nous n'avons toujours aucune idée de l'interface non gérée. Quoi qu'il en soit, vous avez accepté une réponse et la question est fermée. Je suis émerveillé par l'intérêt de cette question. Je ne sais pas pourquoi il y a tellement d'activité, mais malheureusement, vous avez reçu une énorme quantité de conseils médiocres. Il ne devrait y avoir aucune réponse car votre question n'est pas bien spécifiée. Jusqu'à ce que vous puissiez spécifier l'interface que vous essayez de rencontrer, il est inutile pour quiconque d'écrire du code. Que vous effectuez tout ce essai et une erreur est juste une perte de temps énorme.


@DavidHeffernan Il y a tellement d'activité parce que le principal (int Argc, Char ** ARGV) est une entrée assez courante à l'autochtone C DLL, et il n'y a pas une seule question Stackoverflow qui répond à la procédure de maréchal. Certainement pas les présumées de questions en double (on parle de char *, l'autre à propos de Cons-Char **).


Vous n'avez toujours pas défini l'interface. Habituellement, ARGV est de longueur argc + 1 avec une entrée finale qui est null. est-ce le cas ici? Vous avez mal posé la question mal et j'ai reçu beaucoup de mauvais avis.


@DavidHeffernan Tout ce que je reçois du vendeur, est qu'ils s'attendent à ce qu'elles s'attendent à ce que le premier argument soit le nom de l'exécutable, aucune mention de l'argument de NULL final. Je vérifierai à nouveau pour être sûr. En tout cas, je l'ai enfin fini (voir ma dernière modification). La fonction attendait une gamme de pointeurs sur des tampons à cordes et non des tampons de cordes concaténés comme on m'a dit initialement. Une fois que j'ai fait ce changement, l'application a commencé à travailler comme prévu. Votre point sur NULL argument est un bon, car il peut simplement fonctionner par accident maintenant, si la mémoire au-delà de mes indications est à zéro.


Il suffit de vérifier, ils utilisent argc pour quitter la boucle d'analyse.


3 Réponses :


0
votes

Pouvez-vous modifier le type de paramètre de déclaration Dllimport sur StringBuilder [] ? Ensuite, vous pouvez appeler la fonction comme: xxx


0 commentaires

3
votes

Je pense que vous devrez peut-être utiliser le maréchal.

var a = (char*)Marshal.StringToCoTaskMemAuto("myString");
char** = &a;


2 commentaires

Il a compilé, sans que je doive changer la signature Dllimport, mais je me retrouve toujours avec une exception d'épingle à la mervokestackimbalance. L'appel semble fonctionner partiellement, car je vois la 3e partie DLL connecter la fenêtre de sortie. Je dois vérifier quelque chose d'autre ne le causant pas, avant d'accepter votre réponse. +1 pour l'instant.


@ Eternal21 Compte tenu de l'erreur de Pinvokestackestackancement, je vais deviner que vous aviez raison de "une gamme de chaînes", même si cela serait vraiment utile de voir plus de détails sur la bibliothèque tierce. Steve est sur le bon chemin que vous devriez utiliser le maréchal afin de convertir des chaînes à des pointeurs dangereux, mais je pense que vous devriez comprendre ce que ces chaînes sont censées être, puis construire votre matrice de vos cordes.



2
votes

L'équivalent de C Char ** est un octet entièrement épinglé [] [] [] en C # (et entièrement épinglé, je veux dire le tableau externe et tout l'intérieur tableaux). Si vous souhaitez passer des chaînes C #, vous devrez les convertir en byte, par exemple avec encoding.ascii.getBytes .


5 commentaires

J'ai décidé de «marshaler» manuellement les données comme un tampon d'octets unique []. Ive a édité ma question avec le nouveau code que j'ai proposé. On dirait que cela devrait fonctionner, mais la bibliothèque n'aime pas cela, je me retrouve avec violation d'accès. Pas sûr si c'est parce que j'ai utilisé IntPTR au lieu d'octets **.


Votre signature Dllimport est probablement fausse. Il est peu probable que la fonction s'attend à un C # Char ** , qui serait comme un wchar_t ** dans C. Il devrait probablement être simplement string [] Au lieu de cela et laissez p / invoquer traiter avec le marshalling, comme dans les questions en double liées.


La fonction ne s'attend pas à un C # Char **, c'est pourquoi j'ai utilisé un octet comme vous l'avez suggéré.


Mais alors la signature C # Dllimport est fausse car elle utilise le C # Char .


Tous fixés maintenant dans ma dernière modification. Votre commentaire d'octets a été utile.