Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

19.05.2011, 09:05

C# DllImport

HAllo!
ich würde gerne eine in C++ geschriebene dll importieren und in meinem c# code aufrufen.

jetzt hab ich so eine c++ funktion:
char_t* GetVersion(void)
{bla}

und die will ich jetzt aufrufen:
[DllImport(@"C:\PARSER.dll")]
protected static extern String GetVersion();

in dieser zeile:
string version = GetVersion(); kommts dann zu einem fehler und zwar:
"Unable to load DLL 'C:\PARSER.dll': The specified module could not be found

das problem is aber: diese dll, die genau so heißt liegt in C:\... also der pfad stimmt 100%. Jetzt dachte ich mir vielleicht findet er die funktion nicht weil die
ein void argument oder so erwartet und i nix mitgib...

kanns das sein?

lg

2

19.05.2011, 09:14

mir haben andere libs gefehlt die die dll brauchte.

Jetzt gehts !

lg

3

19.05.2011, 09:48

jetzt hab ich aber gleich noch eine frage, bei der ich ohne hilfe nicht recht vorankomme:
in besagter dll hab ich folgendes konstrukt:

struct 1 : enthält enum und ein union mit ints und floats und ... drin
struct 2: enthält char* und struct1

und dann gibts eine funktion Parse(const char * const inputFile, size_t* const statementCnt,
struct2** const statementList)

und ich hab grad keine plan wie ich die korrekt aufrufe.

soweit ich weiß kann ich ein union nicht wirklich in c# nachbilden und muss dann für jedes unionmember ein einzelnes struct
machen?

und wie sollt ich das mit dem ** lösen? hat jemand mit schmierigen dll import sachen erfahrung?

lg

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

19.05.2011, 10:23

Die union kannst du dir mit einem LayoutKind.Explicit und FieldOffset Attributen basteln. Das mit dem Doppelpointer wird interessant. Hast du Kontrolle über die dll? Wofür brauchst du den genau? Den Speicher den die Funktion allokiert wirst du direkt in .Net sowieso nicht verwenden können. Im Notfall müsstest du da z.B. einen IntPtr by ref übergeben und dir alles Weitere dann händisch irgendwie rausholen.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (19.05.2011, 10:32)


5

19.05.2011, 14:16

naja. die parse funktion liest ein file ein und mir dann alles in einen std::vector mit allen statements packt. diese können entweder calls oder zuweisungen sein.
ich hab irgendwo gegoogelt und gefunden, dass wenn ich eine klasse per ref übergebe, sollte das einen ** ergeben.

wie genau meinst du ich kann nicht auf den speicher zugreifen. wenn ich keinen zugriff auf den speicher hab, dann is die dll für mich unbenutzbar.

lg

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

19.05.2011, 16:36

Ich meine du kannst nicht direkt ein .NET Objekt auf diesem Speicher erstellen sondern müsstest in jedem Fall kopieren. Anyway, mal eine rein grundsätzliche Frage: Warum schreibst du deinen Parser nicht einfach in C#?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (19.05.2011, 16:41)


7

23.05.2011, 08:19

sry. ich war übers wochenende weg.

also. naja ich bin nicht der einzige der diese parser dll verwendet und daher wärs gscheiter, wenn ich die bestehende dll verwende und das ganze nicht selber neu schreib.

Mh... also wenn ich da jetzt ein paar structs und dergleichen baue und die funktion mit den richtigen parameter aufrufe kann ich nicht davon ausgehen, dass nach beendigung der fktion auch wirklich meine daten drin stehn?

lg

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

23.05.2011, 10:01

Es wäre möglich, aber der Doppelpointer machts nicht einfach, da wirst du dich vermutlich händisch ums Marshalling kümmern müssen...

9

23.05.2011, 10:13

so. ich hab mich da jetzt weitergespielt und steh jetzt vor folgenden problemen:

ich das mal soweit nachgebaut wie ichs brauch:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Parser_Argument_t
    {
        [FieldOffset(0)]
        public int type;
        [FieldOffset(4)]
        public int int_value;
        [FieldOffset(4)]
        public float float_value;
        [FieldOffset(4)]
        public byte char_value;
        [FieldOffset(4)]
        public string string_value;
    }

    [StructLayout(LayoutKind.Sequential)]
    public class Parser_Statement_t
    {
        public int stp;
        public string name;
        IntPtr argCnt;
        Parser_Argument_t arg;
    }


so bekomme ich diese fehler:
Cannot marshal field 'arg' of type 'GUI.Forms.Parser_Statement_t': There is no marshaling support for this type.

wenn ich jetzt den string nicht an stelle 4 sondern 8 setze gehts zwar, aber es steht etwas drin, das so nicht stimmen kann.


und die zweite sache is der doppelpointer.
ich habe halt nur zugriff auf das erste strucht, dass ich der funktion übergebe.

jetzt weiß ich nur gar nicht wie ich jetzt zugriff auf die anderen bekomme.
ich hab versucht den ** als ein Statement[] zu übergeben, aber das geht gar net...
also nicht:

C-/C++-Quelltext

1
2
protected static extern int Parser_Parse(string inputFile, ref IntPtr statementCnt,
            ref Parser_Statement_t statementList);

sondern:

C-/C++-Quelltext

1
2
protected static extern int Parser_Parse(string inputFile, ref IntPtr statementCnt,
            ref Parser_Statement_t[] statementList);


zu erinnerung die originale c++ funktion schaut so aus:

C-/C++-Quelltext

1
2
3
Parser_Status_t Parser_Parse(
    const char_t* const inputFile, size_t* const statementCnt,
    Parser_Statement_t** const statementList)


lg

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

23.05.2011, 10:29

so bekomme ich diese fehler:
Cannot marshal field 'arg' of type 'GUI.Forms.Parser_Statement_t': There is no marshaling support for this type.

wenn ich jetzt den string nicht an stelle 4 sondern 8 setze gehts zwar, aber es steht etwas drin, das so nicht stimmen kann.

Wundert mich dass das überhaupt geht wenn du da mit class arbeitest und nicht mit struct...


und die zweite sache is der doppelpointer.
ich habe halt nur zugriff auf das erste strucht, dass ich der funktion übergebe.

jetzt weiß ich nur gar nicht wie ich jetzt zugriff auf die anderen bekomme.
ich hab versucht den ** als ein Statement[] zu übergeben, aber das geht gar net...

Wie gesagt

C#-Quelltext

1
protected static extern int Parser_Parse(string inputFile, out IntPtr statementCnt, out IntPtr statementList);

Und dann z.B. damit oder damit deine einzelnen Objekte rauskopieren...

Eine Alternative wäre evtl. unsafe Code, dort kannst du direkt mit Pointern hantieren.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (23.05.2011, 10:42)


Werbeanzeige