Seite 2 von 2

Verfasst: 03.02.2009 14:30
von DarkDragon
Argh halt, warte. So bekommst du irgendwann Stackprobleme:

Code: Alles auswählen

import tango.sys.SharedLib;
import Integer = tango.text.convert.Integer;
import tango.stdc.stringz;

typedef extern (C) void function(char* arg) tdll2;
tdll2 dll2;

void main() {
    int stack1, stack2;
    auto library = SharedLib.load("Test.dll");

    if(library !is null) {
        dll2 = cast(tdll2) library.getSymbol("dll2");

        asm {
            mov [stack1], ESP;
        };

        dll2(toStringz("Hallo von D"));

        asm {
            mov [stack2], ESP;
        };

        dll2(toStringz(Integer.toString(stack2 - stack1) ~ " -> sollte 0 sein, ist es aber nur bei extern(Windows)"));

        library.unload();
    }
}
Desshalb musst du das extern(C) zu extern(Windows) machen:

Code: Alles auswählen

import tango.sys.SharedLib;
import Integer = tango.text.convert.Integer;
import tango.stdc.stringz;

typedef extern (Windows) void function(char* arg) tdll2;
tdll2 dll2;

void main() {
    int stack1, stack2;
    auto library = SharedLib.load("Test.dll");

    if(library !is null) {
        dll2 = cast(tdll2) library.getSymbol("dll2");

        asm {
            mov [stack1], ESP;
        };

        dll2(toStringz("Hallo von D"));

        asm {
            mov [stack2], ESP;
        };

        dll2(toStringz(Integer.toString(stack2 - stack1) ~ " -> sollte 0 sein, ist es aber nur bei extern(Windows)"));

        library.unload();
    }
}
[EDIT]

Ich würde den Code

Code: Alles auswählen

ProcedureDLL dll2(*ptr)
   MessageRequester("pb MessageRequester", PeekS(*ptr))
EndProcedure
dennoch so schreiben:

Code: Alles auswählen

ProcedureDLL dll2(peter.s)
   MessageRequester("pb MessageRequester", peter.s)
EndProcedure
Ist im Grunde genau dasselbe, nur übersichtlicher für manche.

Verfasst: 03.02.2009 16:02
von gekkonier
Hier nochmal das ganze HOWTO aufbereitet:

1. in Purebasic eine pbdll.dll compilieren. Source:

Code: Alles auswählen

ProcedureDLL dll2(str.s)
   MessageRequester("pb MessageRequester", str)
EndProcedure
2. in D(Tango) folgendes Programm erstellen:

Code: Alles auswählen

import tango.sys.SharedLib;
import tango.stdc.stringz;

typedef extern (Windows) void function(char* arg) tdll2;
tdll2 dll2;

void main() {
    auto library = SharedLib.load("pbdll.dll");
    if(library !is null) {
        dll2 = cast(tdll2) library.getSymbol("dll2");
        dll2(toStringz("Hallo von D"));
        library.unload();
    }
} 
mit dmd main.d compilieren.
Durch die tango.sys.SharedLib erspart man sich das convertieren mit implib, wichtig ist noch das extern(Windows), damit da auch alles passt ;)

Vielen Dank nochmal!

Verfasst: 17.03.2009 15:51
von gekkonier
Und das ganze für Phobos und Tango, den mühsamen Weg gehend:

Benötigt wird noch zusätzlich zur dmd Toolchain das Programm implib aus
ftp://ftp.digitalmars.com/bup.zip

1.)
hallodll.dll compilieren:

Code: Alles auswählen

ProcedureDLL hallo(var.s)
   MessageRequester("ich bin in pb", var, 0)
EndProcedure
2.)
main.d anlegen:

Code: Alles auswählen

module Hallo;
pragma(lib, "hallodll.lib");
extern (Windows) {
	void hallo(char* str);
}
void main() {
	hallo("hallo von d");
}
3.)
jetzt wirds lustig:

Code: Alles auswählen

implib /s hallodll.lib hallodll.dll
dmd main.d
Es kommt dann folgende Fehlermeldung:

Code: Alles auswählen

OPTLINK (R) for Win32  Release 8.00.1
Copyright (C) Digital Mars 1989-2004  All rights reserved.
main.obj(main)
 Error 42: Symbol Undefined _hallo@4
--- errorlevel 1
4.)
Diese Information verwenden wir für eine hallodll.def:

Code: Alles auswählen

LIBRARY 'hallodll.dll'
EXPORTS
_hallo@4 = hallo
5.)
Jetzt nochmal den Zweisatz, diesmal aber mit der def-Datei!

Code: Alles auswählen

implib /s hallodll.lib hallodll.def
dmd main.d
Die Prozedur funktioniert sowohl für Phobos als auch Tango, falls wer beide Runtimes verwendet.