alias in C# bekannt machen vorher war es ein typedef **gelöst**
-
Hallo Leute,
ich habe einen typedef in einer C++ .Net Dll
typedef char tDllArray[12];
jetzt möchte ich diese Dll in C# benutzen. Dort kennt er aber den Type nicht.
Wie mache ich den bekannt?
MfG
-
Das geht nicht direkt.
Du muss in C# ein entsprechenden Typen selbst definieren.
SimonEdit
Oder noch besser in der C++/CLI DLL kein typdef benutzen, sondern entweder einen richtigen Typen (z.B. Klass oder Struct) oder aber eben einfach ein char Array....
-
das Problem ist einige meiner Funktionen der Dll benutzen den Typ als übergabe bzw. Rückgabeparameter
d.h ich muß irgend einen Type in C++ .Net deklarieren den C# kennt und den ich dann aber in der Dll wieder in obigen Typ wandeln kann.
Wie mache ich so etwas?
MfG
Edit: genau da hängt es mit der Arry definition wie ich in c++ struckts und enums deklariere die c# kennt weiß ich aber wie mache ich das bei solchen Typen?
-
public char[12] tKSDllArray;
so geht es nicht da er das public nicht kennt
MfG
-
Du musst das Mapping auf einen C# kompatiblen Typen in der C++/CLI DLL vornehmen.
Zeig doch mal ein minimal Code Ausschnitt wie Du deinen Typedef verwendest und wie Du ihn in C# verwenden möchtest.
Du hast ähnliche Probleme wie bei deinem letzen Post mit den WinAPI Callbacks...
Simon
-
namespace DllDotNet { public char[12] tKSDllEPC; }
DllDotNet.tKSDllEPC test = new tKSDllEPC;
ja genau die Probleme sind änlich. Das Beispiel mit den Callbacks werde ich dann nacher ausprobieren wollte erst mal die Typen hinbekommen.
MfG
Edit:
public enum tKSErrorCode { Error_NoError = 0, Error_NotInitialisized, Error_NoValidHandle, Error_KommunicationNotInitialisized, Error_KommunicationToLong, Error_KommunicationTimeout, Error_KommunicationNoMemory, Error_KommunicationUnspecified, Error_NoMemory };
geht doch auch
-
hat jemand eine Idee?
-
Für was brauchst Du im C# Teil tKSDllEPC?
Versuche das Mapping in der C++/CLI DLL zu machen. Abstrahiere die Dinge, so dass sie sinnvoll werden. Was Du versuchst ist 1:1 den native Code nach manged zu bringen. Das ist jedoch sehr schnell nicht mehr möglich.
Simon
-
Ist tKSDllEPC eine ID, ein String, ein Name? Was ist der Inhalt und wie füllst Du ihn?
-
das soll ein array of char sein mit 12 chars größe.
meine Frage ist genau die wie deklariere ich in CLI genau das array, das ich es in C# nutzen kann. im CLI Code werde ich die daten dann von meinem C arry in das neue CLI Array Kopieren damit c# meine Daten verarbeiten kann.
MfG
-
das soll ein array of char sein mit 12 chars größe.
Ja, natürlich, das sehe ich. Aber wie wird es gebraucht? Was bedeutet es?
Geht ev. einfach ein System::String^ ??
oder ein array<char>^ ??
-
nein es Wird kein String in den Bytes kommen Nummern die als IDs interpretiert werden.
-
Hmm, warum muss es dafür unbedingt ein Char-Array sein?
-
ich denke muß es nicht also es sollte ein Typ sein der für 12 Bytes platz hat.
ich wollte nur wissen wie man ein char array deklariert in CLI damit man es in C# nutzen kann.
Ich bin auch mit einem anderen Datentyp zufrieden den C# kennt und der 12 byte Platz bietet.
MfG
Edit: ich habe sonst immer MFC programmiert und in .NET noch nix gemacht, deshalb kenne ich die Typen von C# nicht.
-
Dann ist wohl für dich das einfachste arraySystem::Char^ zu benutzen.
Ein managed char array. In C# mit char[] anzusprechen. Allerdings kommt irgendwann der Punkt wo Du das managed array in ein native array bringen musst...Trotzdem:
Was ich Dir immer noch nicht entlocken konnte ist, was die Absicht hinter den 12 Bytes sind. Denn wenn diese bekannt ist, könnte eine sinnvolle Abstraktion gemacht werden, das ganze anständig gekapselt werden und sogar noch für .NET verfügbar gemacht werden (als Klasse oder Struct).Simon
-
diese 12 Byte ergeben eine ID die später meistens Hexadezimal dargestellt wird anhand dieser ID kann man dann bestimmte einträge aus Datenbaken holen
-
So.. hier mal ein Bsp:
C++/CLI DLL, File: Lib.h
#pragma once using namespace System; using namespace System::Text; using namespace System::Diagnostics; namespace Lib { public ref class ID { public: ID(array<Byte>^ data) : _data(data) { if (data == nullptr) { throw gcnew ArgumentNullException(); } if (data->Length != 12) { throw gcnew ArgumentException(); } } ID(Byte b0, Byte b1, Byte b2, Byte b3, Byte b4, Byte b5, Byte b6, Byte b7, Byte b8, Byte b9, Byte b10, Byte b11) { _data = gcnew array<Byte>(12); _data[0] = b0; _data[1] = b1; _data[2] = b2; _data[3] = b3; _data[4] = b4; _data[5] = b5; _data[6] = b6; _data[7] = b7; _data[8] = b8; _data[9] = b9; _data[10] = b10; _data[11] = b11; } virtual String^ ToString() override { StringBuilder^ sb = gcnew StringBuilder(); for (int i = 0; i < _data->Length; ++i) { sb->AppendFormat(L"0x{0:x2}", _data[i]); if (i < _data->Length - 1) { sb->Append(L" "); } } return sb->ToString(); } property array<Byte>^ Data { array<Byte>^ get() { return _data; } } private: array<Byte>^ _data; }; } bool Marshal(Lib::ID^ id, char* buffer, size_t length) { array<Byte>^ data = id->Data; if (length != data->Length) { return false; } for (int i = 0; i < data->Length; ++i) { buffer[i] = data[i]; } return true; }
C# Code
using System; using System.Diagnostics; namespace App { class Program { static void Main(string[] args) { Lib.ID id = new Lib.ID(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c }); Debug.WriteLine(id.ToString()); } } }
Dabei kannst Du die Funktion Marshal der Library innerhalb dieser benutzen um eine ID in ein natives char array zu kopieren.
Simon
-
Von der C#-Seite aus sollte es einfach sein, mit MarshalAs(UnmanagedType.ByValArray, ...) einen kompatiblen value type ("struct") zu erzeugen. Die "struct" auf der C++ Seite bleibt dabei einfach unmanaged.
Eine andere Möglichkeit wäre einfach 3 ints in eine ref struct zu packen, mit LayoutKind.Sequential:
[StructLayout(LayoutKind::Sequential, Pack = 8)] ref struct MyID { int part1; int part2; int part3; };
Hier müsste man auf der C++ Seite dann vermutlich einen pin_ptr verwenden. Oder halt die drei ints in drei getrennten Zuweisungen irgendwo reinkopieren.
-
danke erst mal für das Beispiel oben
ich fange aber erst mal mit den struckts an.
Folgendes struckt habe ich als c++ code:
typedef struct { tDllComType m_ComType; union { struct { TByte m_ubPort; //COM port TDWord m_uwBaudrate; //baud rate tDllParityMode m_DllParityMode; TBool m_bAreTwoStopBits; } m_RS232; struct { TDWord m_udwDeviceNumber; } m_USB; struct { TBool m_bIPAddressType; //0 = IPv4 or 1 = IPv6 TBool m_bIsIPAddress; union { TByte m_rgubIPAddress[16]; //IPaddress TByte m_rgubNetworkName[16]; } m_KindOfConnection; } m_Ethernet; } m_ComConfigParameters; } tComConfigData;
dazu der code in CLI
public enum tKSRWDllComType { KSRW_DLLCT_RS232 = 0, //RS232 connection KSRW_DLLCT_USB, //USB connection KSRW_DLLCT_ETHERNET //Ethernet connection }; public enum tKSRWDllParityMode { KSRW_PM_NOPARITY = 0, KSRW_PM_ODDPARITY, KSRW_PM_EVENPARITY, KSRW_PM_FORCEDTOONE, KSRW_PM_FORCEDTOZERO, }; public struct tKSRWComConfigData { tKSRWDllComType m_ComType; union { struct { TByte m_ubPort; //COM port TDWord m_uwBaudrate; //baud rate tKSRWDllParityMode m_DllParityMode; TBool m_bAreTwoStopBits; } m_RS232; struct { TDWord m_udwDeviceNumber; } m_USB; struct { TBool m_bIPAddressType; //0 = IPv4 or 1 = IPv6 TBool m_bIsIPAddress; union { TByte m_rgubIPAddress[16]; //IPaddress TByte m_rgubNetworkName[16]; } m_KindOfConnection; } m_Ethernet; } m_ComConfigParameters; };
jetzt kann ich zwar in C# eine Variable von dem Typ instanziieren kann aber nicht auf die einzelnen Teile zugreifen:
DllDotNet.tKSRWComConfigData ComConfig = new DllDotNet.tKSRWComConfigData(); ComConfig.m_ComType= KSRW_DLLCT_RS232;
er meldet:
Fehler CS1061: "ReaderDllDotNet.tKSRWComConfigData" enthält keine Definition für "m_ComType", und es konnte keine Erweiterungsmethode "m_ComType" gefunden werden, die ein erstes Argument vom Typ "ReaderDllDotNet.tKSRWComConfigData" akzeptiert. (Fehlt eine Using-Direktive oder ein Assemblyverweis?)weiterhin brauche ich noch äquivalente typen für
#define TBool unsigned char
#define TByte unsigned char
#define TsByte signed char
#define TWord unsigned short
#define TsWord signed shortMfG
-
Sag mal.. könnte es sein, dass der Aufwand für neu schreiben in C# kleiner ist als eine C++/CLI Bridge zu bauen?
-
Nein die Dll hat ca. 100 Funktionen davon einige Callbacks und insgesamt ein paar (ca. 10) eigen definierte typen als zusätzliche übergabeparameter.
Außerdem müßte mann dann änderungen immer an beiden Codestellen machen, was ich viel schlimmer finde.
Die Callbacks hab ich jetzt müssen nur noch die typen passend gemacht werden. Mein Problem ist ich weiß nicht so recht welche Typen es in CLI gibt und welche davon dann auch in C# verfügbar sind. Zum Test habe ich mal ein char definiert als übergabeparameter aber öffensichtlich scheint auch der c# char typ anders zu sein denn das ging auch nicht.
Aber in dem struckt ist alles mögliche drion was ich benötige, deshalb hab ich das mal angegeben.
MfG