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

11

23.05.2011, 10:53

mh... ich hab mir deine links zwar no net angeschaut aber zur unsafe sache will ich was sagen.

ich habs probiert und ich darf keinen pointer auf ein struct/classe machen, den wiederrum structs drin hat...

es geht einfach net...
Cannot take the address of, get the size of, or declare a pointer to a managed type ('Statement_t')

i schau mir mal deine links an...
thx für deine hilfe
lg

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

12

23.05.2011, 18:44

Warum solltest Du das auch machen wollen? Schreib die Member doch einfach alle hintereinander da rein. Und nimm wie dot schon sagte ein struct und keine class.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

13

24.05.2011, 08:14

ok... also nur das ich das richtig verstanden habe wiederhole ich es nochmal:

- ich verwandle meine classes in structs.
- ich verwende PtrToStructure und umgekehrt um auf meine daten zugreifen zu können

jetzt is nur die frage wie ich das problem wegbekomme, dass ich in meiner "union" den string nicht an die selbe stelle
setzen kann wie alle anderen (offset = 4).
vielleicht gehts wenn ich den string als char* marshalle oder so?

edit: wenn ich beide classes in structs wandle funktionierts net mehr. da hab ich dann keine werte mehr drin stehn.
wenn ich statement als class und arg als struct mach gehts. umgekehrt nicht. und beides klassen geht auch...

edit2:
Ich habs jetzt folgendermaßen gelöst:
protected static extern int Parser_Parse(string inputFile, out IntPtr statementCnt,
out IntPtr statementList);

auf die Daten zugreifen geht so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
  IntPtr statePtr = Marshal.AllocHGlobal(Marshal.SizeOf(state));
                Marshal.StructureToPtr(state, statePtr, false);

                int retval = Parser_Parse(pathToFile_, out statementCnt, out statePtr);

                ret = (Parser_Status_t)retval;

                Parser_Statement_t st =
                 (Parser_Statement_t)Marshal.PtrToStructure(statePtr, typeof(Parser_Statement_t));
                state = st;


und das geht auch. zwei sachen funktionieren noch nicht wirklich.
erstens bekomm ich das union konstrukt nicht auf die reihe und zweitens weiß ich nicht wirklich wie ich auf das statement array zugreifen kann.
ich habe einen IntPtr aufs erste element und kann mir das auch in ein struct umwandeln und dann die daten sehen aber wie komme ich zum zweiten element?

intptr++ will er mich nicht lassen.

wie könnt ich das denn lösen?

lg

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


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

14

24.05.2011, 10:46

Probiers mal so:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[StructLayout(LayoutKind.Explicit)]
public struct 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)]
  [MarshalAs(UnmanagedType.LPStr)]
  public string string_value;
}

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



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.

Es gäbe sicher auch vergleichbare Libraries für .NET, warum muss es denn um jeden Preis diese sein?

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


15

24.05.2011, 11:04

nein... geht leider auch nicht.

ja es gibt sicher solche libs für .net.

nur hier das problem: ich schrieb das für die arbeit und da bekomm ich die dll und es hat geheißen is soll sie verwenden und nicht selber neu schreiben.
sonst würd ichs eh selbst schreiben...

er meckert immer dass ein object type da meinen speicher überlappt. string is doch ein objecttype oder?
allerdings wüsst ich nicht, wie ichs sonst machen könnt...

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

16

24.05.2011, 11:10

Was genau meckert er und wie genaut sieht dein Code nun aus?

Und ich hab nicht von selber neu schreiben geredet sondern davon sich eine fertige passende .NET Bibliothek zu suchen (gibts sicher wie Sand am Meer, du bist garantiert nicht der Erste der mit C# was parsen will). Das würde alles eben um Lichtjahre weniger kompliziert machen. Die dll zu verwenden um die dll zu verwenden is imo jedenfalls kein guter Grund sich mit dem ganzen Marshalling rumzuschlagen wenns auch einfach funktionieren könnte. Managed/Unmanaged Interop, P/Invoke, etc. sind Dinge die ich mir freiwillig nur antun würde wenns keine Alternative gibt. Ich wette in der Zeit die du nun schon reingesteckt hast um die dll zum Laufen zu bekommen hättest du schon locker eine gleichwertige oder bessere Lösung in .NET zusammenbasteln können...

Der einzige rationell vertretbare Grund der mir einfällt warum eine Firma sich auf diese dll versteifen könnte wäre dass es sich dabei um eine speziell entwickelte, praxisbewährte Lösung für ein hochspezielles Problem handelt in der viel Know-How steckt sodass eine Neuentwicklung eines solchen Systems angesichts der Tatsache dass diese anfangs voller Bugs sein wird natürlich weniger attraktiv erscheint. Wenn ich mir aber das Interface gegen das du coden willst so anschau bezweifle ich stark dass das hier der Fall ist. Sieht mir eher aus wie die x-te Parserlibrary, und keine besonders komplexe noch dazu. Und davon gibts auch für .NET genug, da muss man nicht krampfhaft eine C++ Library reinhämmern...

Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von »dot« (24.05.2011, 11:36)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

17

24.05.2011, 11:53

Natürlich kanns sein dass ich irgendein wesentliches Detail warum du genau diese dll verwenden musst übersehen hab. Und wenn deine Firma es sich unbedingt einbildet dass es so sein muss dann kannst du eh nix machen, ich würd nur mindestens einen Versuch unternehmen ihnen Vernunft einzureden. Ich werd natürlich weiterhin versuchen dir zu helfen das Ding zum Laufen zu bringen wenns sein muss. Und wenns wirklich nicht geht: Als letzten Ausweg könnte man sich immer noch mit C++/CLI einen .NET Wrapper für das Ding bauen. Nur dann sind wir endgültig in einem Land aus dem einst nur die tapfersten und erfahrensten aller Krieger lebend zurückkehrten. Und die Geschichten die sie von dort mitgebracht haben sind wahrlich schauderhaft...

ich habe einen IntPtr aufs erste element und kann mir das auch in ein struct umwandeln und dann die daten sehen aber wie komme ich zum zweiten element?

Indem du die Größe eines Elements zum Pointer addierst? ++ macht keinen Sinn da es sich um keinen richtigen Pointer handelt und der Typ auf den gezeigt wird unbekannt ist.

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »dot« (24.05.2011, 12:04)


Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

18

24.05.2011, 11:57

Mehr als WinAPI funktionen aus managed code hab ich im bereich schnittstelle zwischen managed und unmanaged noch nicht gemacht, aber ich wäre jetzt einfach mal so naiv und würde anstatt des strings einfach byte-array versuchen.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

19

24.05.2011, 12:13

Erklär vielleicht auch mal was genau du eigentlich anstellen willst. .NET bietet dir nämlich z.B. auch die Möglichkeit überhaupt zur Laufzeit C# Code zu kompilieren und auszuführen...

20

25.05.2011, 08:19

so. ich danke dir dot für deine hilfe und kann berichten, dass es jetzt lauft.
ich muss noch schaun ob sich irgendwo bugs eingeschlichen haben, es sieht aber gut aus.

offenbar is es komplett egal ob offset fürn string bei 8 und nicht bei 4 liegt. da steht das richige drin.

Naja diese Parser dll is schon ein größeres projekt der firma, das ein paar monate lang schon lauft. Und viele andere Abteilungen verwenden die auch und ich programmiere halt in C# bei dem was ich mache und da is es halt doch gescheit, dass ich einmal schaue, dass die dll gscheit lauft bei mir, weil ich mich um die wartung und erweiterung nicht kümmern muss.
Wenn ich jetzt etwas anderen zusammenbastle dann heißts gleich : " zwei implementationen fürs selbe problem...bla...bla...bla..."

so und nun zur implementation:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[StructLayout(LayoutKind.Sequential)]
    public struct Parser_Statement_t
    {
        public Parser_StatementType_t stp;
        public string name;
        public IntPtr argCnt;
        public IntPtr arg;
    }   

//wie gesagt das statement hat fürn string als fieldoffset jetzt 8
//so mach ich den eigentlichen aufruf:
                Parser_Statement_t state = new Parser_Statement_t();
                IntPtr statePtr = Marshal.AllocHGlobal(Marshal.SizeOf(state));
                Marshal.StructureToPtr(state, statePtr, false);

                int retval = Parser_Parse(pathToFile_, out statementCnt, out statePtr);

                ret = (Parser_Status_t)retval;
 
                state = 
                 (Parser_Statement_t)Marshal.PtrToStructure(statePtr, typeof(Parser_Statement_t));

//und so incrementere ich pointer:
        public static IntPtr Increment(IntPtr ptr, int cbSize)
        {
            return new IntPtr(ptr.ToInt64() + cbSize);
        }


und so scheints eigentlich zu gehn.


Noch zur diskussion warum ich die dll verwende:
Ich habe eignetlich keinen rechten plan was die dll eigentlich macht.
Es wurde mit Bison und Lexer ein parser generiert. Und diese files sind dann in C und die dll, welche ich verwende, is in C++ und benutzt den
generierten parser.

Und da mir bei einem 20 zeilen #defines wirklich schlecht wird, dachte ich die schnellere lösung is es in C# zu marshallen.
Außerdem hab ich jetzt nicht die super ahnung von irgendwelchen grammatiken oder so, die man braucht um so einen parser generieren zu lassen.

für alle interessierten:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#define YYRHSLOC(Rhs, K) ((Rhs)[K])
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N)                \
    do                                  \
      if (YYID (N))                                                    \
    {                               \
      (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;    \
      (Current).first_column = YYRHSLOC (Rhs, 1).first_column;  \
      (Current).last_line    = YYRHSLOC (Rhs, N).last_line;     \
      (Current).last_column  = YYRHSLOC (Rhs, N).last_column;   \
    }                               \
      else                              \
    {                               \
      (Current).first_line   = (Current).last_line   =      \
        YYRHSLOC (Rhs, 0).last_line;                \
      (Current).first_column = (Current).last_column =      \
        YYRHSLOC (Rhs, 0).last_column;              \
    }                               \
    while (YYID (0))
#endif


und so weiter is der C code...

lg und nochmal danke dot!

Werbeanzeige