Interoperabilità c#-c++

venerdì 15 giugno 2012 - 09.37
Tag Elenco Tags  C#  |  .NET 4.0

evalgher Profilo | Newbie

Buongiorno a tutti,
per prima cosa, grazie per la vostra attenzione, qualsiasi chiarimento, suggerimento o consiglio, è ben accetto.
Vi espongo il mio problema:
Ho creato una libreria sviluppata in c# che, al suo interno, dovrebbe richiamare una funzione appartenente ad un'altra libreria scritta in c++(RTIME.DLL).
La chiamata, apparentemente, sembra non dare problemi, visto che, mi restituisce valori che mi aspetto, tranne che per un dettaglio. Qui di seguito riporto il codice della dll scritta in c++:

int RTIME_API RTIME_Read_Canale(int Canale,double* value){.....}

il problema risiede proprio nel secondo parametro presente in questa funzione; infatti, essa, si aspetta un puntatore di tipo double. Fino a qui nessun problema.Il metodo presente nella libreria .net scritta in c# è il seguente:

[DllImport("RTIME.DLL")]
public static extern int RTIME_Read_Canale(int numero,ref Double valore)

quando questo metodo viene richiamato, non mi genera nessun errore, ma, pur passandogli per riferimento la variabile valore, inizializzata ad 1, essa mi riporta un valore errato (0) mentre, io mi aspetterei di trovarmi un valore di 16381.
Il metodo viene richiamato nel seguente modo:

double tmp=1;
valore=tmp;
error_code=RTIME_Read_Canale(Convert.ToInt32(support.getNumeroCanale()),ref valore)

Per quale motivo, tutti i dati sono passati correttamente, mentre questo maledetto puntatore, passato per riferimento(purtroppo nn posso modificare la libreria RTIME), viene modificato in maniera sbagliata?

Grazie mille a tutti!

luigidibiasi Profilo | Guru

probabilmente perché c# utilizza ""puntatori"" che non sono compatibili con c++

per passare per riferimento devi utilizzare le classi specifiche di .NET che ti permettono di creare un puntatore comune ad entrambi...

si può fare solo che ora non ricordo bene come si chiamano quelle classi


>>motd
vedi un po' qua
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/e8cd6cae-e8e9-4df0-a816-6ea8a45343ff/

il problema è comune a molti ... googla "how to pass pointer from c# to c++"

Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

evalgher Profilo | Newbie

ok provo a fare qualche ricerca riguardo queste classi. Grazie mille per la celerità nel rispondere

edit:

per ora ancora nulla...qualche altra soluzione?

luigidibiasi Profilo | Guru

vagamente ricordo una keywords... qualcosa con pinned dentro...

mi puoi allegare il progetto (almeno nella sua parte non funzionante) con la dll che provo?


forse è una coda del genere

'# il double da passare Dim p As Double = 100 '# allocazione di memoria non gestita Dim x As IntPtr = Marshal.AllocCoTaskMem(64) '# metti la dimensioen dei double Marshal.StructureToPtr(p, x, False)

in x hai il puntatore da passare alla funzione...


Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

evalgher Profilo | Newbie

Ho inserito il codice che mi hai suggerito, (x come puntatore), ma il risultato è il medesimo. Inoltre ho provato a dichiarare tutta la classe unsafe, ma mi ritorna sempre 0!
La cosa sconvolgente è questa: lo stesso tipo di interrogazione l'ho eseguita scrivendola in vb.net, ottenendo il risultato voluto; ecco il codice:

Dichiarazione:

Private Declare Function RTIME_Read_Canale Lib "RTIME.DLL" (ByVal Canale As Int32, ByRef Value As Double) As Int32

Richiamata:

Private mValue As Double
RTIME_Read_Canale(Me.ID, mValue)

davvero strano!
(purtroppo non posso passare i file perchè non ne sono il proprietario, e non ho l'autorizzazione)

luigidibiasi Profilo | Guru

scusami ...

in vb.net funziona il metodo e in c# no?
Luigi Di Biasi


http://www.dibiasi.it/
http://netsell.dibiasi.it - ecomm software -
http://blogs.dotnethell.it/luigidibiasi/
http://yadamp.unisa.it/ - YADAMP CMS -

evalgher Profilo | Newbie

esatto! Con il codice che ho riportato, riesco a leggere il valore!
Vorrei fare in modo da non utilizzare linguaggi diversi per risolvere questa cosa...Qualche altra idea?

evalgher Profilo | Newbie

Ho trovato finalmente la soluzione: la chiamata effettivamente deve essere fatta in questo modo:

error_code = RTIME_Read_Canale(Convert.ToInt32(support.getNumeroCanale()),ref valore);


Precedentemente non mi funzionava, perchè, semplicemente, non inizializzavo il device, richiamando le sue routine di start.

Ringrazio tutti coloro che si sono prodigati a rispondermi.

Buona giornata
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5