Announcement

Collapse
No announcement yet.

C#-Struktur als Parameter für eine DLL-Funktion ( C++ )

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • C#-Struktur als Parameter für eine DLL-Funktion ( C++ )

    Hallo C#-User,

    ich habe erneut ein Problem mit der Umsetzung bzw. Nutzung einer DLL-Funktion. Diesmal mit der Übergabe einer Struktur. Die Funktionsbeschreibung der DLL-Funktion lautet im Original:

    <PRE>short ExternDllFunction(char Parameter_1, Parameter_2 = Struktur* StrukturDefinition)</PRE>

    Es wird als Parameter_2 also ein Pointer auf eine Struktur vom Typ "StrukturDefinition" erwartet. Leider habe ich bei der Umsetzung so meine Schwierigkeiten. Ich habe in C# die folgend Struktur erzeugt:

    <PRE>/// Struktur
    public struct myStructure
    {
    public string para_1, para_2, para_3;

    public myStructure(string para_1, string para_2, string para_3)
    {
    this.para_1 = value_1;
    this.para_2 = value_2;
    this.para_3 = value_3;
    }
    }</PRE>

    Ich habe folgende Fragen:

    1. Wie muss ich die externe Funktion deklarieren, damit als 2. Parameter eine Struktur vom Typ "StrukturDefinition" erwartet wird.

    2. Wie übergebe ich diese Struktur nun als 2. Parameter an die externe DLL-Funktion?

    Ich habe den Aufruf in der folgenden Form definiert, was natürlich falsch ist.

    <PRE>[DllImport("extern.dll", CharSet = CharSet.Ansi)]
    public static extern short ExternDllFunction(StringBuilder Parameter_1, StringBuilder Parameter_2);</PRE>

    Der Aufruf funktioniert zwar, aber die Funktion liefert nicht das korrekte Ergebnis. Kann jemand helfen?

    jlo

  • #2
    Hi
    <P>
    Ich denke das sollte etwa so aussehen:
    <PRE>
    [DllImport("extern.dlL", CharSet = CharSet.Ansi)]
    public static extern short ExternDllFunction(char Parameter_1, StrukturDefinition Parameter_2);
    </PRE>
    Ev. hilft Dir MSDN weiter:<P>
    http://www.microsoft.com/germany/msdn/library/net/csharp/MitCSharpArbeitenVerwendenVonWin32UndAnderenBiblio theken.mspx
    <P>
    Deine Strktur muss ungefähr folgende Form haben:
    <PRE>
    struct StrukturDefinition {
    // Hier kommen die Members deiner struct.
    }
    </PRE>
    Falls Parameter_2 als Output Parameter gedacht ist, brauchts ev. noch ref oder out.
    <P>
    Wie sieht denn deine struct in unmanaged code aus?
    <P>
    Simo

    Comment


    • #3
      Hallo Simon,

      ich habe mir den Link schon einmal angeschaut. Der scheint weiter zu helfen. Ich komme jedoch erst am Wochenende dazu, die Informationen umzusetzen.

      Erst einmal vielen Dank!

      jl

      Comment


      • #4
        Hallo Leute,

        also, ich habe am Wochenende ´mal einiges versucht. Hier meine Struktur:

        <PRE>/// Struktur myStructure
        public struct myStructure
        {
        public string value_1;
        public string value_2;
        public string value_3;
        public string value_4;
        }</PRE>

        Hier mein DLL-Aufruf. Es wird die Struktur als Pointer übergeben...

        <PRE>
        [DllImport("extern.dll", CharSet = CharSet.Ansi)]
        public static extern short GetMyTestData(string param_1, ref myStructure myStructure);
        </PRE>

        Hier mein Aufruf der Methode:

        <PRE>
        private void button1_Click(object sender, System.EventArgs e)
        {
        string myParam_1 = "blabla";

        myStructure _myStructure = new myStructure();
        _myStructure.value_1 = new string(' ', 4) + "\0";
        _myStructure.value_2 = new string(' ', 11) + "\0";
        _myStructure.value_3 = new string(' ', 5) + "\0";
        _myStructure.value_4 = new string(' ', 17) + "\0";

        try
        {
        short returnCode = GetMyTestData(myParam_1, ref _myStructure);

        if ( returnCode == 0 )
        {
        ....
        }
        else
        {
        ....
        }
        }
        catch ( Exception ex )
        {
        this._progInfo.Fehler(ex);
        }
        }
        </PRE>

        Also, die Funktion ansich läuft! Aber sie liefert kein Ergebnis!

        Nun ist mir bekannt, dass ein Struktur ein vorgegebenes Muster hat. Die Struktur, die ich hier verwende, hat auch ein vorgeschriebenes Muster. Da ich aber auch weiß, dass für die Rückgabe von Werten aus einer externen DLL, keine Strings verwendet werden können und die Möglichkeit, die Struktur-Werte als StringBuilder zu übergeben ausgeschlossen ist, stehe ich erneut vor einem Rätsel, was ich dringend lösen muss.

        Es muss doch möglich sein, diese C++-Funktion mit C# korrekt aufrufen zu können und auch die Werte zurück zu bekommen, die lt. Funktion geliefert werden sollen...

        Hat jemand eine Idee

        Comment


        • #5
          Hi<P>
          Du erwartest das Ergenis in der Struktur, nach erflogreichem Funktionsaufruf, oder?
          <P>
          Hast Du die Möglichkeit den C++ Code zu debuggen?
          <P>
          Ist diese Funktion von einer Library und kannst Du die Ändern falls nötig?
          <P>
          Simo

          Comment


          • #6
            So, ich habe ein kleines Bsp. gemacht.
            <P>
            C++ Code:
            <PRE>
            struct MyStructure {
            char m1;
            char* m2;
            };

            extern "C" __declspec(dllexport) short __cdecl GetMyTestData(MyStructure*);

            short GetMyTestData(MyStructure* p) {
            p->m1 = 'b';
            p->m2 = "abcd";
            return (short) 5;
            };
            </PRE>
            C# Code:
            <PRE>
            using System;
            using System.Runtime.InteropServices;
            using System.Diagnostics;

            namespace TestApp {

            class Class1 {

            [STAThread]
            static void Main(string[] args) {
            MyStructure p;
            short ret = GetMyTestData(out p);
            Debug.WriteLine(p.m1);
            Debug.WriteLine(p.m2);
            }

            struct MyStructure {
            public char m1;
            public string m2;
            }

            [DllImport("ExternLib.dll")]
            static extern short GetMyTestData(out MyStructure p);
            }
            }
            </PRE>
            Falls Du die ganze VS Solution möchtest (mit C++ und C# Code), kannst Du hier eine Mail Adr. posten. Ich werde Dir dann das Bsp. Zukommen lassen.
            <P>
            Übrigens, falls Du die Struktur "nur" übergibst um Daten aus der Funktion zurückzuliefern, kannst Du sie per "out" übergeben (im Gegensatz zu "ref"). Dann musst Du die Struktur vorher nicht initialisieren.
            <P>
            Simo

            Comment


            • #7
              Hallo Simon,

              nach einigem "Hin und Her" habe ich die Funktion nun endlich zum Laufen gebracht!!!! HURRA...

              Ursache des Fehlers war "Art der Struktur" in C#. Da "C++"-Code unmanaged ist, brachte erst der Umweg über die [MarshalAS]-Methode das richtige Ergebnis.

              Hier das Beispiel, welches nun tatsächlich funktioniert...

              /// Strukturdefinition ///

              <PRE>
              public struct myStructure
              {
              [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public string value_1;
              [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 31)] public string value_2;
              [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string value_3;
              [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 25)] public string value_4;
              }
              </PRE>

              /// DLLImport ///

              <PRE>
              [DllImport("extern.dll", CharSet = CharSet.Ansi)]
              public static extern short GetMyTestData(string param_1, out myStructure _myStructure);
              </PRE>

              /// Aufruf der Methode ///

              <PRE>
              private void button3_Click(object sender, System.EventArgs e)
              {
              string param_1 = "blabla" + "\0";

              try
              {
              myStructure _myStructure;
              short returnCode = GetMyTestData(para_1, out _myStructure);

              if ( returnCode == 0 )
              {
              }
              else
              {
              }
              }
              catch ( Exception ex )
              {
              this._progInfo.Fehler(ex);
              }
              }
              </PRE>

              Ich hoffe, dass damit auch anderen geholfen ist, die das gleiche "nervige" Problem irgendwann einmal "haben werden"

              Und Dir - Simon - vielen Dank für Deine Unterstützung...

              Gruß
              jl

              Comment

              Working...
              X