<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Safearray an Dll übergeben&#x2F;zurückgeben]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich möchte gerne aus VB ein array an eine C-DLL übergeben dort dann damit arbeiten und ein weiteres array wieder zurückgeben. Da in VB jedem array eine safearray struktur zu grunde liegt muss ich es in C als safearray behandeln (richtig?).<br />
Leider kenne ich mich mit safearrays in C nicht sonderlich aus, würde das was ich gemacht habe (siehe unten) überhaupt funktionieren? Oder gibt es da noch einen anderen weg?<br />
Momentan scheint es nicht zu funktionieren, leider hab ich keine Ahnung wie ich in meiner DLL debuggen kann um das alles mal zu überprüfen! Könnte mir bitte jemand sagen wie ich das am besten anstelle?!</p>
<p>Der Datentyp des input und output arrays in VB ist jeweils Byte. In meiner C-Funktion möchtes ich dann den input in ein float array kopieren um damit arbeiten zu können. Das 'Ergebnis' meiner Funktion liegt dann in einem char array vor was ich dann in das byte-array in VB kopieren möchte. Der equivalente Datentyp zu Byte in VB ist meiner Meinung nach unsigned char in C. Müsste ich dann mein Ergebnis erst noch von char nach unsigend char konvertieren oder kann ich es einfach so in das safearray schreiben.</p>
<p>So sieht (grob) meine Funktion in der DLL aus:</p>
<pre><code class="language-cpp">declspec__ (dllexport) int __stdcall MeineFunktion (LPSAFEARRAY *input_frame, LPSAFEARRAY *output_bytes, int size)
{

    int MAX_NB, nbBytes;
    long int i;

    char *output_buffer;
    float *input_buffer;

    /* alloc memory for input */
    input_buffer = new float [size];

    /* copy input safearray to floatarray */
    for(i=0; i&lt;size; i++)
        SafeArrayGetElement(input_frame[ i ], &amp;i, &amp;input_buffer[ i ]);

    /* other functions */

    /* delete memory used for input */
    delete input_buffer;

    /* get frame size in bytes */
    MAX_NB = /* other function */

    /* alloc memory for output */
    output_buffer = new char [MAX_NB];

            /* other functions - return char* */

    /* copy to output safearray */
    for(i=0; i&lt;MAX_NB; i++)
        SafeArrayPutElement(output_bytes[ i ], &amp;i, &amp;output_buffer[ i ]);

    /* delete memory used for output */
    delete output_buffer;

    return nbBytes;
}
</code></pre>
<p>Der aufruf in VB geschieht folgendermaßen, also müssten die zeiger im Funktionskopf der DLL-Funktion dann auf meine arrays in VB zeigen (richtig?):</p>
<pre><code>'EineKlasse

Private m_nbBytes As Long
'[...]

Private Declare Function MeineFunktion Lib &quot;irgendeine.dll&quot; (ByRef InputFrame() As Byte, _
            ByRef OutputBytes() As Byte, ByVal ArraySize As Long) As Long

Public Sub Methode(InputArray() As Byte, OutputArray() As Byte)
   m_nbBytes = MeineFunktion(InputArray, OutputArray, UBound(InputArray))
End Sub
'[...]
</code></pre>
<pre><code>Dim clsKlasse As New EineKlasse

Dim InputArray() As Byte
Dim OutputArray() As Byte

'Funktionsaufruf
clsKlasse.Methode InputArray, OutputArray
</code></pre>
<p>Danke und gruss<br />
Sören</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/65315/safearray-an-dll-übergeben-zurückgeben</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 15:05:02 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/65315.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 18 Feb 2004 10:55:04 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Wed, 18 Feb 2004 10:55:04 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich möchte gerne aus VB ein array an eine C-DLL übergeben dort dann damit arbeiten und ein weiteres array wieder zurückgeben. Da in VB jedem array eine safearray struktur zu grunde liegt muss ich es in C als safearray behandeln (richtig?).<br />
Leider kenne ich mich mit safearrays in C nicht sonderlich aus, würde das was ich gemacht habe (siehe unten) überhaupt funktionieren? Oder gibt es da noch einen anderen weg?<br />
Momentan scheint es nicht zu funktionieren, leider hab ich keine Ahnung wie ich in meiner DLL debuggen kann um das alles mal zu überprüfen! Könnte mir bitte jemand sagen wie ich das am besten anstelle?!</p>
<p>Der Datentyp des input und output arrays in VB ist jeweils Byte. In meiner C-Funktion möchtes ich dann den input in ein float array kopieren um damit arbeiten zu können. Das 'Ergebnis' meiner Funktion liegt dann in einem char array vor was ich dann in das byte-array in VB kopieren möchte. Der equivalente Datentyp zu Byte in VB ist meiner Meinung nach unsigned char in C. Müsste ich dann mein Ergebnis erst noch von char nach unsigend char konvertieren oder kann ich es einfach so in das safearray schreiben.</p>
<p>So sieht (grob) meine Funktion in der DLL aus:</p>
<pre><code class="language-cpp">declspec__ (dllexport) int __stdcall MeineFunktion (LPSAFEARRAY *input_frame, LPSAFEARRAY *output_bytes, int size)
{

    int MAX_NB, nbBytes;
    long int i;

    char *output_buffer;
    float *input_buffer;

    /* alloc memory for input */
    input_buffer = new float [size];

    /* copy input safearray to floatarray */
    for(i=0; i&lt;size; i++)
        SafeArrayGetElement(input_frame[ i ], &amp;i, &amp;input_buffer[ i ]);

    /* other functions */

    /* delete memory used for input */
    delete input_buffer;

    /* get frame size in bytes */
    MAX_NB = /* other function */

    /* alloc memory for output */
    output_buffer = new char [MAX_NB];

            /* other functions - return char* */

    /* copy to output safearray */
    for(i=0; i&lt;MAX_NB; i++)
        SafeArrayPutElement(output_bytes[ i ], &amp;i, &amp;output_buffer[ i ]);

    /* delete memory used for output */
    delete output_buffer;

    return nbBytes;
}
</code></pre>
<p>Der aufruf in VB geschieht folgendermaßen, also müssten die zeiger im Funktionskopf der DLL-Funktion dann auf meine arrays in VB zeigen (richtig?):</p>
<pre><code>'EineKlasse

Private m_nbBytes As Long
'[...]

Private Declare Function MeineFunktion Lib &quot;irgendeine.dll&quot; (ByRef InputFrame() As Byte, _
            ByRef OutputBytes() As Byte, ByVal ArraySize As Long) As Long

Public Sub Methode(InputArray() As Byte, OutputArray() As Byte)
   m_nbBytes = MeineFunktion(InputArray, OutputArray, UBound(InputArray))
End Sub
'[...]
</code></pre>
<pre><code>Dim clsKlasse As New EineKlasse

Dim InputArray() As Byte
Dim OutputArray() As Byte

'Funktionsaufruf
clsKlasse.Methode InputArray, OutputArray
</code></pre>
<p>Danke und gruss<br />
Sören</p>
]]></description><link>https://www.c-plusplus.net/forum/post/461905</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/461905</guid><dc:creator><![CDATA[Spontex]]></dc:creator><pubDate>Wed, 18 Feb 2004 10:55:04 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Wed, 18 Feb 2004 11:21:13 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">/* alloc memory for input */ 
input_buffer = new float [size]; 

/* dynam. Speicherplatz von einem array sollte so freigegeben werden: */

delete [] input_buffer;
</code></pre>
<p>kann sein das du das übersehn hast....</p>
<p>cu surf.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/461934</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/461934</guid><dc:creator><![CDATA[surfman.]]></dc:creator><pubDate>Wed, 18 Feb 2004 11:21:13 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Wed, 18 Feb 2004 12:20:56 GMT]]></title><description><![CDATA[<p>Nachdem Du das Problem mit dem falschen Löschen beseitigt hast, solltest Du Dir mal diesen Artikel in der MS KB ansehen: <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;207931" rel="nofollow">HOWTO: Pass Arrays Between Visual Basic and C</a></p>
<p>Außerdem bekommst Du vom Array kein Array geliefert. Es sind also nur input_frame[0] und output_frame[0] gültig. Desweiteren solltest Du erstmal checken, ob es überhaupt ein Array ist, wie Du es erwartest. Du willst ein eindimensionales Array. Z.B.:</p>
<pre><code class="language-cpp">UINT nDimensions = SafeArrayGetDim(*input_frame);

if(nDimension != 1)
{
    // Huh?
}
</code></pre>
<p>Und noch besser ist's, wenn Du zusätzlich noch den im Array gespeicherten Daten-Typen ermittelst (SafeArrayGetVartype) und mit der Forderung vergleichst.</p>
<p>Auch kannst Du bei solchen Arrays nicht einfach bei 0 zu zählen anfangen. Du mußt vielmehr die Unter- und Obergrenze abfragen:</p>
<pre><code class="language-cpp">long lLBound;  // Untere Grenze
SafeArrayGetLBound(*input_frame, 1, &amp;lLBound);

long lUBound;  // Obere Grenze
SafeArrayGetUBound(*input_frame, 1, &amp;lUBound);

/* copy input safearray to floatarray */
for(i = lLBound; i &lt;= lUBound; i++)
    SafeArrayGetElement(*input_frame, &amp;i, &amp;input_buffer[i]);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/461988</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/461988</guid><dc:creator><![CDATA[-King-]]></dc:creator><pubDate>Wed, 18 Feb 2004 12:20:56 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Wed, 18 Feb 2004 13:14:03 GMT]]></title><description><![CDATA[<p>-King- schrieb:</p>
<blockquote>
<p>Nachdem Du das Problem mit dem falschen Löschen beseitigt hast, solltest Du Dir mal diesen Artikel in der MS KB ansehen: <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;207931" rel="nofollow">HOWTO: Pass Arrays Between Visual Basic and C</a></p>
</blockquote>
<p>Nette Lektüre, ich arbeite Sie gerade durch <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<blockquote>
<p>Außerdem bekommst Du vom Array kein Array geliefert. Es sind also nur input_frame[0] und output_frame[0] gültig.</p>
</blockquote>
<p>Wie meinst du das? Ja die Zeiger input_frame und output_bytes zeigen jeweils auf das erste element des arrays und von da aus kann ich dann das array per index auslesen usw. - oder nicht ??</p>
<blockquote>
<p>Auch kannst Du bei solchen Arrays nicht einfach bei 0 zu zählen anfangen. Du mußt vielmehr die Unter- und Obergrenze abfragen:</p>
</blockquote>
<p>OK, hab ich eingebaut.</p>
<p>Nachtrag:<br />
Könntest du mir sagen wie ich am besten innerhalb der DLL debuggen kann??</p>
]]></description><link>https://www.c-plusplus.net/forum/post/462042</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/462042</guid><dc:creator><![CDATA[Spontex]]></dc:creator><pubDate>Wed, 18 Feb 2004 13:14:03 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Wed, 18 Feb 2004 14:45:08 GMT]]></title><description><![CDATA[<p>Spontex schrieb:</p>
<blockquote>
<p>Wie meinst du das? Ja die Zeiger input_frame und output_bytes zeigen jeweils auf das erste element des arrays und von da aus kann ich dann das array per index auslesen usw. - oder nicht ??</p>
</blockquote>
<p>Nein, die Zeigen <strong>nicht</strong> auf Array-Elemente, sondern auf das Array selbst. Du darfst da <strong>nicht</strong> mit einem Index rübergehen.</p>
<pre><code class="language-cpp">// Deine Variante - FALSCH!!
SafeArrayGetElement(input_frame[ i ], ...);

// Meine Variante (siehe oben) - richtig
SafeArrayGetElement(input_frame[0], ...);
</code></pre>
<p>Welches Element Du aus dem einen einzigen Array bekommst, gibt der Index im zweiten Parameter von SafeArrayGetElement an.</p>
<blockquote>
<p>Könntest du mir sagen wie ich am besten innerhalb der DLL debuggen kann??</p>
</blockquote>
<p>Einfach einen Breakpoint in der Dll setzen. Unter dem Menüpunkt 'Debuggen' findest Du das Item 'Prozesse'. Da wählst Du nun VB aus. Wird der Breakpoint erreicht, wird das Programm an dieser Stelle unterbrochen. Jedenfalls funktioniert das bei mir. Wie das bei Dir geht, hängt natürlich vom verwendeten Werkzeug ab.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/462150</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/462150</guid><dc:creator><![CDATA[-King-]]></dc:creator><pubDate>Wed, 18 Feb 2004 14:45:08 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Thu, 19 Feb 2004 08:47:06 GMT]]></title><description><![CDATA[<p>Vielen dank, endlich mal jemand der Ahnung von Safearrays hat!</p>
<p>-King- schrieb:</p>
<blockquote>
<p>Einfach einen Breakpoint in der Dll setzen. Unter dem Menüpunkt 'Debuggen' findest Du das Item 'Prozesse'. Da wählst Du nun VB aus. Wird der Breakpoint erreicht, wird das Programm an dieser Stelle unterbrochen. Jedenfalls funktioniert das bei mir. Wie das bei Dir geht, hängt natürlich vom verwendeten Werkzeug ab.</p>
</blockquote>
<p>Mmhh wenn ich das bei mir im VC6 so mache, deaktiviert er mir beim start alle breakpoints, was so ja nicht im Sinne des Erfinders ist. Was mache ich da falsch?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/462827</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/462827</guid><dc:creator><![CDATA[Spontex]]></dc:creator><pubDate>Thu, 19 Feb 2004 08:47:06 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Thu, 19 Feb 2004 09:34:40 GMT]]></title><description><![CDATA[<p>OK, so siehts mittlerweile aus:</p>
<pre><code class="language-cpp">declspec__ (dllexport) int __stdcall MeineFunktion (SAFEARRAY **input_frame, SAFEARRAY **output_bytes, int input_size)
{

	int MAX_NB, nbBytes = 0;
	long i, in_LBound, in_UBound, out_LBound, out_UBound;

	char *output_buffer;
	float *input_buffer;

	SAFEARRAYBOUND re_array[1];

	/* get input array lbound */
	SafeArrayGetLBound(*input_frame, 1, &amp;in_LBound); 

	/* get input array ubound */
	SafeArrayGetUBound(*input_frame, 1, &amp;in_UBound); 

		/* alloc memory for input */
		input_buffer = new float [input_size];

		/* copy input safearray to float-array */
		for(i = in_LBound; i &lt;= in_UBound; i++) 
			SafeArrayGetElement(*input_frame, &amp;i, &amp;input_buffer[i]);

		/* ** other functions ** */

		/* delete memory used for input */
		delete [] input_buffer;

		/* get frame size in bytes */
		MAX_NB = /* ** other function ** */

		/* alloc memory for output */
		output_buffer = new char [MAX_NB];

		/* set new elements in bound */
		re_array[0].cElements = MAX_NB;

		/* redim array to new size */
		SafeArrayRedim(*output_bytes, re_array);

		/* get output array lbound */
		SafeArrayGetLBound(*output_bytes, 1, &amp;out_LBound); 

		/* get output array ubound */
		SafeArrayGetUBound(*output_bytes, 1, &amp;out_UBound); 

		output_buffer = /* ** other function - return char* ** */

		/* copy char-array to output safearray */
		for(i=out_LBound; i&lt;out_UBound; i++)
			SafeArrayPutElement(*output_bytes, &amp;i, &amp;output_buffer[i]);

		/* delete memory used for output */
		delete [] output_buffer;

	return nbBytes;
}
</code></pre>
<p>So müsste ich doch das VB array aus meiner DLL raus neudimensionieren können:</p>
<pre><code class="language-cpp">SAFEARRAYBOUND re_array[1];

/* set new elements in bound */
re_array[0].cElements = ANZAHL_DIM;

* redim array to new size */
SafeArrayRedim(*output_bytes, re_array);
</code></pre>
<p>Danke und Gruss<br />
Sören</p>
]]></description><link>https://www.c-plusplus.net/forum/post/462870</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/462870</guid><dc:creator><![CDATA[Spontex]]></dc:creator><pubDate>Thu, 19 Feb 2004 09:34:40 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Thu, 19 Feb 2004 12:19:21 GMT]]></title><description><![CDATA[<p>Du solltest die Struktur richtig initialisieren:</p>
<pre><code class="language-cpp">re_array[0].cElements = ANZAHL_DIM;
re_array[0].lLbound   = out_LBound;  // &lt;-- fehlt bei Dir!
</code></pre>
<p>BTW: Wie groß sind denn Deine Arrays im Mittel? Aber einer gewissen Größe gibt es eine wesentlich schnellere Möglichkeit des Kopierens:</p>
<pre><code class="language-cpp">VARTYPE vt = VT_EMPTY;
SafeArrayGetVartype(*input_frame, &amp;vt);

if(VT_R4 != vt)
{
    // Es sind keine floats im Array gespeichert!
    // Was nun?
}

if(input_size &gt; abs(in_UBound - in_LBound))
{
    // input_size ist groesser als das Array!
    // Was nun?
}

input_buffer = new float [input_size];

float* pData = NULL;
SafeArrayAccessData(*input_frame, (void**)&amp;pData);
CopyMemory(input_buffer, pData, input_size * sizeof(float));
SafeArrayUnaccessData(*input_frame);
</code></pre>
<p>Aber sicherer ist's natürlich mit SafeArrayGetElement/ PutElement. Musst schauen, was für Dich geeigneter ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/463054</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/463054</guid><dc:creator><![CDATA[-King-]]></dc:creator><pubDate>Thu, 19 Feb 2004 12:19:21 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Thu, 19 Feb 2004 12:28:48 GMT]]></title><description><![CDATA[<p>Spontex schrieb:</p>
<blockquote>
<p>Mmhh wenn ich das bei mir im VC6 so mache, deaktiviert er mir beim start alle breakpoints, was so ja nicht im Sinne des Erfinders ist. Was mache ich da falsch?</p>
</blockquote>
<p>Für den VC6 mußt Du einen 'harten' Breakpoint verwenden. Darum brauchst Du Dich glücklicherweise nicht selbst zu kümmern, sonst kannst auf eine API-Funktion zurückgreifen: <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/debugbreak.asp?frame=true" rel="nofollow">DebugBreak</a>.</p>
<p>Du setzt nun diesen 'harten' Breakpoint gleich an den Funktions-Anfang, z.B. so:</p>
<pre><code class="language-cpp">declspec__ (dllexport) int __stdcall MeineFunktion (SAFEARRAY **input_frame, SAFEARRAY **output_bytes, int input_size)
{
    DebugBreak();
    .
    .
    .
</code></pre>
<p>Und so übersetzt Du jetzt die Dll. Danach geht's über das Menü 'Erstellen'. Im SubMenu 'Debug Starten' wählst Du das Item 'Verbinden mit Prozess'. Der Debugger sollte jetzt beim Erreichen des Breakpoints anhalten. Du wirst dann aber vermutlich noch zweimal auf F11 drücken müssen, bevor Du das Disassembly-Window schliessen kannst. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/463069</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/463069</guid><dc:creator><![CDATA[-King-]]></dc:creator><pubDate>Thu, 19 Feb 2004 12:28:48 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Thu, 19 Feb 2004 12:32:38 GMT]]></title><description><![CDATA[<blockquote>
<p>BTW: Wie groß sind denn Deine Arrays im Mittel? Aber einer gewissen Größe gibt es eine wesentlich schnellere Möglichkeit des Kopierens:</p>
</blockquote>
<p>Im Mittel ca. 10000 Einträge.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/463077</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/463077</guid><dc:creator><![CDATA[Spontex]]></dc:creator><pubDate>Thu, 19 Feb 2004 12:32:38 GMT</pubDate></item><item><title><![CDATA[Reply to Safearray an Dll übergeben&#x2F;zurückgeben on Thu, 19 Feb 2004 12:35:27 GMT]]></title><description><![CDATA[<p>Spontex schrieb:</p>
<blockquote>
<p>Im Mittel ca. 10000 Einträge.</p>
</blockquote>
<p>Dann solltest Du die Möglichkeit mit CopyMemory nutzen, IMO.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/463080</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/463080</guid><dc:creator><![CDATA[-King-]]></dc:creator><pubDate>Thu, 19 Feb 2004 12:35:27 GMT</pubDate></item></channel></rss>