Laden...

c++ code zu c#: unsigned char ** buffer

Erstellt von Dragon-Sword vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.597 Views
D
Dragon-Sword Themenstarter:in
125 Beiträge seit 2008
vor 14 Jahren
c++ code zu c#: unsigned char ** buffer

Hallo zusammen,

wie kann man soetwas in c# darstellen?

uc**buffer

uc -> unsigned char



IntPtr ptrBuffer = Marshal.AllocHGlobal(16635);
Byte[] buffer = new Byte[16635];

Marshal.Copy(buffer, 0, ptrBuffer, buffer.Length);


habe es so verstanden, dass ich hier einen Pointer auf einen Pointer brauche.

Nachdem Byte[] schon ein Pointer ist benötige ich nur noch einen Pointer auf das Byte[] ist das richtig?

3.971 Beiträge seit 2006
vor 14 Jahren

unsigned char* -> byte[]-Array
unsigned char** als Funktionsparameter wäre byte[]-Array mit ref-Schlüsselwort

ein Zeiger auf ein Zeiger wird außer bei Parameterübergabe(ByRef) in C# nicht verwendet.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

S
8.746 Beiträge seit 2005
vor 14 Jahren

Zeig doch mal den C++-Code.

BTW: ref byte[] wird nur mit COM-Arrays gemarshallt. Hier müßte ref IntPtr verwendet werden.

D
Dragon-Sword Themenstarter:in
125 Beiträge seit 2008
vor 14 Jahren

int DECL2 doUpload(daveConnection*dc, int * more, uc**buffer, int*len, int uploadID){



[DllImport("libnodave.dll")]
        protected static extern int doUpload(IntPtr daveConnection, ref int more, ref IntPtr ptrBuffer, ref int len, int uploadID);
        private int DoUpload(int uploadID)
        {
            int ret = int.MinValue;
            int len = int.MinValue;
            IntPtr ptrBuffer = Marshal.AllocHGlobal(16635);
            Byte[] buffer = new Byte[16635];

            Marshal.Copy(buffer, 0, ptrBuffer, buffer.Length);

            int more = int.MinValue;//0 -> fertig | 1 -> es kommt noch was
            do
            {
                ret = doUpload(this.daveConnection.pointer, ref more,ref ptrBuffer , ref len, uploadID);
            }
            while (more == 1);

            String s = Marshal.PtrToStringAnsi(ptrBuffer, 16635);


            return ret;
        }

der buffer bleibt nur immer leer

D
Dragon-Sword Themenstarter:in
125 Beiträge seit 2008
vor 14 Jahren

Kann mir hier keiner weiterhelfen?

S
401 Beiträge seit 2008
vor 14 Jahren

Naja,

int DECL2 doUpload(daveConnection*dc, int * more, uc**buffer, int*len, int uploadID){

Die Information ist für den Ar..h. Folgendes ist möglich*buffer ist ein Zeiger auf einen Zeiger

int m = 1;
int * ptr = &m;          /* ptr ist Zeiger auf int */
int ** ptrptr = &ptr;    /* ptrptr ist Zeiger auf int-Zeiger */

*buffer ist eine Zweidimensionales Array

double ** matrix;            // double[][] matrix;
matrix = new double *[10];
matrix[1] = new double[50];  // *(matrix+1) = new double[50];

Sag, was es ist und jemand wird dir Helfen.

Gruß,
Thomas

D
Dragon-Sword Themenstarter:in
125 Beiträge seit 2008
vor 14 Jahren

int DECL2 doUpload(daveConnection*dc, int * more, uc**buffer, int*len, int uploadID){
    PDU p1,p2;
    int res, netLen;
    p1.header=dc->msgOut+dc->PDUstartO;
    _daveConstructDoUpload(&p1, uploadID);
    res=_daveExchange(dc, &p1);
    if (daveDebug & daveDebugUpload) {
	LOG2("error:%d\n", res);
	FLUSH;
    }	
    *more=0;
    if(res!=daveResOK) return res;
    res=_daveSetupReceivedPDU(dc, &p2);
    *more=p2.param[1];
    if(res!=daveResOK) return res;
    netLen=p2.data[1] /* +256*p2.data[0]; */ /* for long PDUs, I guess it is so */;
    if (*buffer) {
	memcpy(*buffer,p2.data+4,netLen);
	*buffer+=netLen;
	if (daveDebug & daveDebugUpload) {
	    LOG2("buffer:%p\n",*buffer);
	    FLUSH;
	}    
    }
    *len+=netLen;
    return res;
}

D
Dragon-Sword Themenstarter:in
125 Beiträge seit 2008
vor 14 Jahren

So könnte es gehen:


 [DllImport("libnodave.dll")]
        protected static extern int doUpload(IntPtr daveConnection, ref int more, IntPtr ptrBuffer, ref int len, int uploadID);
        private int DoUpload(int uploadID)
        {
            int ret = 0;

            IntPtr ptr = Marshal.AllocHGlobal(16635);

            IntPtr ptrptr = Marshal.AllocHGlobal(ptr);

            int more = int.MinValue;//0 -> fertig | 1 -> es kommt noch was
            try
            {
                do
                {
                    try
                    {
                        doUpload(this.daveConnection.pointer, ref more, ptrptr, ref ret, uploadID);
                    }
                    catch (Exception e)
                    {
                        ret = int.MinValue;
                        break;
                    }
                }
                while (more == 1);
            }
            catch (Exception ex)
            {
                ret = int.MinValue;
            }

            Byte[] buffer = new Byte[ret];

            for (int i = 0; i < ret; i++)
            {
                buffer[i] = Marshal.ReadByte(ptr, i);
            }

            return ret;
        }

zumindest stehen werde im Byte[]

S
248 Beiträge seit 2008
vor 14 Jahren

Hallo,


IntPtr ptr = Marshal.AllocHGlobal(16635);
IntPtr ptrptr = Marshal.AllocHGlobal(ptr);

Dieser Code erzeugt keinen Zeiger auf den ersten Buffer, sondern zwei von einander komplett unabhängige Buffer.

Die wohl sinnigste Deklaration wäre (wie schon gesagt) ref IntPtr.

Allerdings kommt dann das nächste Problem ...
In deinem Code wird der allokierte Speicher nicht wieder freigegeben, was man natürlich noch einbauen könnte. Jedoch wird einem der Zeiger auf den allokierten Speicher ...

\*buffer+=netLen;

unter der Nase weg verändert ... (guter Stil?). Zwar wird der veränderte Wert in len wieder zurückgegeben, aber nun muss man entweder wieder rückwerts rechnen, oder sich den Zeiger doppelt vorhalten um auf die Daten zuzugreifen und den Speicher wieder freizugeben.

Wenn ich eine Funktion mit einem Buffer habe, gehe ich davon aus, dass der Buffer gefüllt wird mit Daten. Dabei kann ich ein ggf ein Offset angeben und die Länge des Buffers. Aber eine Funktion sollte dem Aufrufer nicht die Zeiger "verbiegen".

D
Dragon-Sword Themenstarter:in
125 Beiträge seit 2008
vor 14 Jahren

Vielen Dank für die Hilfen, habe einen leichteren Weg gefunden.

daveConnection.getProgramBlock(libnodave.daveBlockType_FC, fc, buffer, ref(len));

macht genau das was ich vor hatte.

S
8.746 Beiträge seit 2005
vor 14 Jahren

(guter Stil?)

Typisches C-Gefrickel. Eigentlich sollte nur der Buffer übergeben werden müssen und die Funktion solltest die Zahl der gesendeten Bytes zurückgeben. Der Aufrufer ist für das Weitersetzen des Puffers zuständig. Macht aber die Funktion gleich mit. Wer sowas baut, dem gehört der Führerschein für den Compiler entzogen.... zumindest DLL sollte er nicht mehr bauen dürfen....