2015-05-04 22 views
15

Provo a chiamare una semplice funzione C da una DLL esterna al di fuori dell'applicazione C#. Questa funzione è definita comeCome faccio a passare un const char * a una funzione C da C#?

void set_param(const char *data) 

ora ho qualche problema di utilizzare questa funzione:

  1. Come faccio a specificare questo "const" in C# -Code? public static extern void set_param(sbyte *data) sembra perdere la parte "const".

  2. Come si può consegnare una stringa C semplice a 8 bit quando si chiama questa funzione? Una chiamata a set_param("127.0.0.1") restituisce un messaggio di errore, "impossibile convertire da" stringa "a" sbyte "" *.

+0

Penso che "public static extern void set_param (string data)" dovrebbe funzionare. –

+1

Penso che troverai molti esempi che troverai qui http://pinvoke.net/ – kenny

risposta

25

Sembra che si prevede di utilizzare il set ANSI char, così si potrebbe dichiarare il P/Invoke in questo modo:

[DllImport("yourdll.dll", CharSet = CharSet.Ansi)] 
public static extern void set_param([MarshalAs(UnmanagedType.LPStr)] string lpString); 

Il marshaller .NET gestisce l'esecuzione di copie di stringhe e la conversione dei dati al tipo giusto per te.

Se si dispone di un errore con uno stack sbilanciato, è necessario impostare la convenzione di chiamata per abbinare il vostro DLL C, ad esempio:

[DllImport("yourdll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] 

Vedere pinvoke.net per un sacco di esempi che utilizzano funzioni API di Windows.

Vedere anche Microsoft's documentation on pinvoking strings.

+0

Ciò provoca un'eccezione: una chiamata alla funzione PInvoke "yourdll.dll :: set_param" ha sbilanciato lo stack. Ciò è probabile perché la firma PInvoke gestita non corrisponde alla firma di destinazione non gestita. – Elmi

+0

@Elmi Quindi è necessario conoscere la convenzione di chiamata della DLL C in modo da poterla specificare nel P/Invoke. Quale convenzione di chiamata usa? –

+0

Matthew Watson: La DLL ha semplici funzioni C non decorate, tutte ANSI-C, __declspec (dllexport) – Elmi

4

A const char* è semplicemente un string in .NET - il lato gestito non (ancora) non comprende la nozione di parametri di sola lettura.

Se si utilizza questo in un contesto P/Invoke, è necessario dichiarare un attributo MarshalAs e impostarlo come LPStr. La firma risultante sarebbe cercare qualcosa sulla falsariga di

[DllImport("SomeModule.dll")] 
public static extern void set_param([MarshalAs(UnmanagedType.LPStr)]string lpString); 

C'è anche questo article on MSDN con più informazioni su come schierare le stringhe nativi per un ambiente gestito.

+0

Non è una stringa in .NET Unicode? Anche con la codifica UTF-8, come funzionerebbe in modo affidabile per ASCII 128-255 (locale specifico, ecc.)? –

+1

@PeterMortensen Per ASCII 128-255 si usa 'LPWStr', che rappresenta una stringa di carattere a 2 byte. A partire da .NET 4.7, 'LPUTF8Str' è stato aggiunto al supporto" nativo "delle stringhe UTF8 piuttosto che restituire un' IntPtr' e gestirli manualmente. Una nota a margine, stringhe in.NET sono UTF-16, che è Microsoft a cui si riferisce come Unicode, ma ha un sapore diverso di Unicode iirc, ma sarebbe corretto affermare che le stringhe in .NET sono Unicode. – aevitas