Autor Beitrag
Tastaro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 404
Erhaltene Danke: 23



BeitragVerfasst: Di 12.09.17 10:34 
Hallo,

ich habe in eine Delphi-DLL eine Funktion die so aussieht:

ausblenden Delphi-Quelltext
1:
function foo(pcResultBuffer: pchar; iResultBufferSize: integer): integer; stdcall;					

In pcResultBuffer wird ein String zurückgegeben. iResultBufferSize teilt die Größe des Buffers mit, auf den pcResultBuffer zeigt.

Diese möchte ich unter C# verwenden.
Ich importiere die DLL dynamisch. Also lege ich einen Typ an (Ist das so richtig?):

ausblenden C#-Quelltext
1:
2:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int FooCallbackType([MarshalAs(UnmanagedType.LPStr)] string resultBuffer, int resultBufferSize);


... der dann verwendet wird

ausblenden C#-Quelltext
1:
private FooCallbackType fooCallback = null;					


Das Auslesen der Funktionszeiger:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
private void GetProcAddresses()
{
    IntPtr funcAddr = IntPtr.Zero;
    
    funcAddr = GetProcAddress(dllHandle, "foo");
    if (funcAddr != IntPtr.Zero)
        fooCallback = (FooCallbackType)Marshal.GetDelegateForFunctionPointer(
            funcAddr, typeof(FooCallbackType));
}


Jetzt fehlt noch der Aufruf der Funktion. Wie mache ich das? Genauer: Wie initialisiere ich den Buffer auf eine bestimmte Länge, damit die Delphi-Funktion was hineinschreiben kann?

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
string resultBuffer;
int bufferSize;
int charsInBuffed;

//hier Buffer-Initialiserierung ????

charsInBuffed = foo(resultBuffer, bufferSize);


Oder muss man das ganz anders machen?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 3897
Erhaltene Danke: 794

Win7
C++, C# (VS 2015/17)
BeitragVerfasst: Di 12.09.17 11:04 
Lies dir mal Using the StringBuilder in Unmanaged API Calls durch (Lösung bei dir also entsprechend "2.4 Using StringBuilder").

Für diesen Beitrag haben gedankt: Tastaro
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2105
Erhaltene Danke: 385

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 12.09.17 11:14 
Guten Tag Tastaro,

ich hätte es so gemacht:

ausblenden C#-Quelltext
1:
2:
[DllImport("DLLname.dll", CallingConvention = CallingConvention.StdCall)]
static extern int foo(string pcResultBuffer, int iResultBufferSize);

Hat dein Anliegen einen Bezug zu der Funktion GetProcAddress():

ausblenden C#-Quelltext
1:
2:
[DllImport("Kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
:?:

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)

Für diesen Beitrag haben gedankt: Tastaro
Tastaro Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 404
Erhaltene Danke: 23



BeitragVerfasst: Di 12.09.17 11:41 
@Frühlingsrolle: GetProcAddress ist schon klar. Das dynamische Einbinden klappt wunderbar.
Ich binde DLLs lieber dynamisch als statisch ein, dann habe ich eine bessere Kontrolle über das Verhalten meines Programms, wenn die DLL nicht vorhanden ist. In manchen Fällen wird sie auch gar nicht benötigt.

Mir ging es hauptsächlich um die Rückgabe eines Strings in einem Buffer.

@Th69: Danke für den Link. Das werde ich mal probieren.
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2105
Erhaltene Danke: 385

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Di 12.09.17 13:53 
Zitat:
Zitat:
Mir ging es hauptsächlich um die Rückgabe eines Strings in einem Buffer.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
string resultBuffer;
int bufferSize;
int charsInBuffed;

//hier Buffer-Initialiserierung ????

charsInBuffed = foo(resultBuffer, bufferSize);

Spricht etwas dagegen bzw. kommen Fehler auf?

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
Tastaro Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 404
Erhaltene Danke: 23



BeitragVerfasst: Mi 13.09.17 11:04 
@Frühlingsrolle: Die Delphi-Funktion erwartet, dass der Speicher des Buffers schon reserviert ist. Mit der Variante gäbe es eine Zugriffstverletzung.

@Th69: Mit dem StringBuilder klappt es super. Danke!