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

21

25.05.2011, 09:12

ok... einen bug hab ich gefunden. alles anderen funktioniert.

die dll hat ja einen filehandle aus dem sie liest und parst.
jetzt muss ich das programm aber immer neu starten, wenn ich etwas in dem file ändere, damit die dll auch das neue file bekommt.

jetzt denk ich es is einfacher einfach die dll neu zu laden und ihr dann das neue file geben.
allerdings find ich nix rechtes zum unloaden einer dll...
ich hab FreeLibrary gefunden aber is das das was ich brauch?

edit:
ok... ich muss leider hinzufügen dass die string geschichte doch noch nicht vom tisch is. es steht zwar was drin, aber nicht das richtige.

also hier nochmal das argmuent:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  [StructLayout(LayoutKind.Explicit)]
    public struct Parser_Argument_t
    {
        [FieldOffset(0)]
        public Parser_ArgumentType_t 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;
    }


und der error:
Could not load Argument_t because it contains an object field at offset 4 that is incorrectly aligned or overlapped by a non-object field
ein marshalAs hat nichts gebracht... gleicher fehler...



lg

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »AlymcGeel« (25.05.2011, 09:43)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

22

25.05.2011, 11:05

Wie sieht Parser_ArgumentType_t aus? Das ist doch sicher größer als 4 Byte oder? Das MarshalAs wirst du auf jeden Fall brauchen. Wie sehen eigentlich die entsprechenden Strukturen in C++ genau aus? Ich würd mal vermuten dass da einfach was mit dem struct-Packing noch nicht zusammenpasst. Hat die dll keine Funktion um ein neues File zu öffnen!? Wenn nein: Wie öffnest du das File was du grad verwendest!?

23

25.05.2011, 11:21

also das original struct schaut so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
typedef struct {
  /** Type of the argument. */
  Parser_ArgumentType_t type; //das is nur ein enum

  /** Used to contain the value of the argument. */
  union {
   int32_t int_value; // is ein int
   float float_value; 
   int8_t char_value; //is ein char
   char_t* string_value;
  } value;
} Parser_Argument_t;


und meine implementation davon is so:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[StructLayout(LayoutKind.Explicit)]
    public struct Parser_Argument_t
    {
        [FieldOffset(0)]
        public Parser_ArgumentType_t type;
        [FieldOffset(4)]
        public int int_value;
        [FieldOffset(4)]
        public float float_value;
        [FieldOffset(4)]
        public byte char_value;
        [FieldOffset(8)] // oder eben 4, weil 8 falsch is
        [MarshalAs(UnmanagedType.LPStr)]
        public string string_value;
    }


ich bin mir ja nicht einmal sicher ob es das problem is.
ich hab nur das problem, dass ich immer die gleichen daten zurückbekomme.
und wenn ich das programm neu starte, und dann das file ändere gehts... also, das was ich als erstes einlese, steht immer drin
obwohl ich jedes mal mein struct neu anlege.

im c++ parser file macht er eig auch jedes mal das file neu auf:

C-/C++-Quelltext

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

  yyin = fopen(inputFile, "r");


also sollte es gehen. ich habs auch durchgesteppt:
ich leg ein neues leerers struct object an. hol mir den IntPtr drauf, ruf die parse funktion auf
und dann mach ich mir aus dem Ptr wieder ein struct und da steht auch das richtige drin.

wenn ich dann das file ändere und nochmal parse steht aber no immer das gleiche drin obwohl ich sicher ein neues struct mitgib und einen neuen Ptr und...
jetzt muss der fehler also bei der dll liegen. Wenn ich die dll dann neu lade (programm neustart) gehts ja...

lg

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

24

25.05.2011, 11:38

Und mit FieldOffset(4) gehts nicht bei dem string (wenn du MarshalAs(UnmanagedType.LPStr) dabei hast)!?
Notfalls vergiss halt dieses struct und mach das ganze Marshalling selber, d.h. nimm den rohen IntPtr den du bekommst und dann Copy() bzw. PtrToStringAuto().

25

25.05.2011, 11:53

nein leider MarshalAs(UnmanagedType.LPStr) is ihm egal...
selbes ergebnis.

ja. nach fast einer woche herumgeärgere mit dem marshal zeug is es eh schon wurscht.

ich werd einen IntPtr mitgeben und den dann auslesen, so wie du vorgeschlagen hast...

ich danke dir noch einmal für deine hilfe...
ohne dich wärens whs 3 wochen gwesen...

edit:
ich marshalle den string jetzt händisch und er wurde zu einem IntPtr und ich muss sagen, ich hab mich gewundert, dass es gleich beim ersten versuch geklappt hat. Jetzt fehlt mir nur noch eine lösung zu dem scheinbar immer offenen filehandle...
ich hab etwas gefunden:
IntPtr hModule = GetModuleHandle(pathToLib_);
FreeLibrary(hModule);
und das geht auch.
Aber ich finde das passende Laden dazu nicht...

weil so kann ichs zwar entladen aber neu laden find ich nicht...

edit2: ok ein LoadLibrary gibts auch. aber das lauft so nicht.
wenn ich die library Freigib und nachher wieder neu lade und dann parse aufrufe, sagt er dass die zu parse gehörende lib nicht da is...

edit3:
ich denke, dass dllImport das problem ist. weil dadurch wird die parse methode fix mit der einmal am anfang geladenen lib verbunden.
wenn ich die lösche und eine Andere neu anlege hilft das auchnix.
Jetzt is die frage: kann ich dynamisch zur laufzeit der parse methode eine neue Dll zuweisen. LoadLibrary gibt mir einen IntPtr mit der adresse zurück.
mir fehlt also nur die funktion der parse methode jetzt diese NEUE lib zuzuweisen ... falls das überhaupt geht.


lg aly

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »AlymcGeel« (25.05.2011, 14:11)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

26

25.05.2011, 15:13

Bau doch bitte einfach eine Funktion zum neu Aufmachen der Datei in die dll ein wo du doch eh den Code davon hast. Wenn du die dll zur Laufzeit dynamisch laden willst musst du alles selbst machen, d.h. die dll mit LoadLibrary() laden und dir dann mit GetProcAddress() einen Function Pointer holen, P/Invoke kannst du dann nichtmehr verwenden.

27

26.05.2011, 07:50

ok. es is so, dass ich zwar den sourcecode habe aber ich darf die dll nicht umändern.
Jetzt werd ich heute aber eh zu den typen gehen und das klären, damit sie so ne funktion einbauen.

ich hab das problem darauf zurückführen können, dass sie einen std::vector haben wo die statements reinkommen und der wird nie gelöscht. außer beim neuladen der dll...

rein theoretisch ich müsste dann doch mit nem fctptr herumarbeiten.

ich Lade die Lib mit LoadLibrary. dann hab ich normalerweise ein handle drauf. und mit FreeLibrary kann ichs wieder zerstören.
aber was genau mach ich mit dem handle? ich bau mir eine delegate funktion und mach mir einen function pointer auf diese funktion mit der adresse der geladenen lib?


edit1: ich hab außerdem ein weiteres problem festgestellt:
IntPtr hLib = LoadLibrary(pathToLib_); ergibt 0. Laut microsoft is das in fehlercode, aber woher weiß ich was genau schiefläuft?
ich hab nämlich so nen code:
LoadLibrary();
Do something with the library function...
FreeLibrary()


edit2:
hLibrary = LoadLibrary(pathToLib_);

if (hLibrary == IntPtr.Zero)
{
string err = Marshal.GetLastWin32Error().ToString();
MessageBox.Show(err);
}

err = 0, was laut MS SUCCESS is. und das kann ja wohl net stimmen...
lg

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »AlymcGeel« (26.05.2011, 08:27)


28

26.05.2011, 10:54

So ein letzes mal:
Ich hab grad mit den zuständigen Leuten gesprochen und sie machen da nen bugfix.

das problem war einfach dass sie eigentlich vergessen hatten den ergebnisvector wieder zu löschen bei mehrmaligem aufrufen...
das hatten die natürlich nicht gemerkt weil sie immer nur ein file geparst haben und dann programm wieder zugemacht hatten...

ich danke dir nocheinmal dot!

und lg

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

29

26.05.2011, 11:06

Ich hab grad mit den zuständigen Leuten gesprochen und sie machen da nen bugfix.

Gut, das ist die einzige vernünftige Lösung. Um ehrlich zu sein kann ichs fast nicht glauben dass diese dll wirklich ein "großes Projekt" dieser Firma sein soll wenn es an derart trivialen Dingen hakt. Klingt mir eher nach etwas was irgendwer schnell mal notdürftig zusammengeschustert hat ;)

Was GetLastWin32Error() angeht: Das funktioniert nur für Funktionen die mit einem entsprechenden Attribut gekennzeichnet sind (vermutlich weil .NET GetLastError() und SetLastError() intern verwendet), genaueres steht eh in der MSDN.

30

26.05.2011, 11:47

naja. Die dll hat ein mitarbeiter programmiert der direkt danach die firma verlassen hat und jetzt fühlt sich keiner so recht zuständig...

außerdem steht es mir als werksstudent ja nicht zu da irgendwas/wen zu kritisieren...gg


allerdings muss ich sagen, obwohls es ein mächtiges herumgeärgere war bin ich froh, dass ich diese seiten vom .net und C# auch einmal kennengelernt habe. Ich hab fast schon gefallen an IntPtrn gefunden...

lg

Werbeanzeige