Laden...

DllImport - LPByte mit Marshal.AlocHGlobal ... CMD-Fenster schließt erst nach etwa 10s (siehe unten)

Erstellt von ibuddy vor 14 Jahren Letzter Beitrag vor 14 Jahren 4.604 Views
I
ibuddy Themenstarter:in
16 Beiträge seit 2009
vor 14 Jahren
DllImport - LPByte mit Marshal.AlocHGlobal ... CMD-Fenster schließt erst nach etwa 10s (siehe unten)

Hallo zusammen,

ich möchte eine Kamera auslesen und habe mit grundlegendem der DLL angefangen. Habe nämlich noch nicht weiter mit DllImport gearbeitet.

Folgendes: Habe eine unmanaged C++-Dll, dort sind alle Funktionen zur Kamera vorhanden.

Konkret hänge ich jetzt an einer Funktion, die bei gegebenem Error-Code eine Beschreibung des Fehlers ausgibt.


DWORD CamUSB_GetErrorString  ( char *  szErrStr,  
                       DWORD  dwMaxLen,  
                       DWORD  dwErrCode   
                      ) 

In nem Beispiel-Code für unmanaged C++ wird sie wie folgt aufgerufen:


  DWORD dwErr;
  UINT  uType;
  char szErrStr[MAX_PATH];     // error string (MAX_PATH is normally around 255)
  char szCaptionStr[MAX_PATH]; // caption string

  memset(szErrStr,     0, sizeof(szErrStr));
  memset(szCaptionStr, 0, sizeof(szCaptionStr));

  dwErr = CamUSB_GetLastError(nDevNr); // read last error code
  CamUSB_GetErrorString( (char*) szErrStr, MAX_PATH, dwErr);

"CAM_USB_GetLastError" liest den letzten gespeicherten Fehler von der Kamera.

Und nun meine Version: Ich habe schon mehrere Varianten durchprobiert:


using System;
...
using System.Runtime.InteropServices;

...

// Get ErrorString - Returns a description for a given error ID. 
        [DllImport(@"C:\CamUsb_API.dll", EntryPoint = "CamUSB_GetErrorString")]
        public static extern ulong GetErrorString(
                                                  StringBuilder buffer,
                                                  //[In, Out] byte[] buffer,      // Buffer to receive the error message 
   
                                                  ulong dwMaxLen,                   // Length of Buffer 
                                                  ulong dwErrCode);                 // Error code which string should be returned

Auzfgerufen wird wie folgt:


static void Main(string[] args)
        {
            byte ndev = 0;
            if (InitCamera() == true)
            { Console.WriteLine("Initialisierung .... success!"); }
            else { Console.WriteLine("Initialisierung .... shit!"); }
            Console.WriteLine("Error Code: " + GetLastError(ndev));
            
            int length = 20;
    // Variante 1
            ulong errorid = 262;  // expected: API warning: your firmware ...
            StringBuilder buffer = new StringBuilder(" ", length);
            ulong ErrorSize = GetErrorString(buffer,(ulong)length,errorid);
            Console.WriteLine(buffer);

    // Variante 2
            //byte[] buffer = new byte[length];
            //for (ulong i = 0; i <1500; i++)
            //{
            //    ulong errorid = i;    //768; // expected: "an other thread is using a camera fuction at the same time
            //    GetErrorString(buffer, (ulong)length, errorid);
            //    foreach (int elem in buffer)
            //    {
            //        Console.Write((char) elem);
            //    };
            //    Console.Write("\n");
            //}


            string wait = Console.ReadLine();

        }

Als Ergebnis erhalte ich aber immer "Command Successful".
Hä? Eigentlich nicht das, was ich erwarte. Entsprechend habe ich bei Variante 2 auch mal alle möglichen Error-IDs durchprobiert ... naja, immer das selbe.

Ich weiß nicht woran es liegen könnte. habe auch schon mit marshal.xxx InPtr usw. probiert oder [MarshalAs(....)] .... usw.

Habt ihr vielleicht ne Ahnung, woran es liegen könnte?

Ich freue mich über jede Hilfe!

Gruß, ibuddy

edit: habe auch mit "ref stringbuilder buffer" ausprobiert. Da gibt er mir die Fehlermeldung:
AccessViolationException wurde nicht behandelt.
Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist.

_Help me work with library. I have dll library wrotre on Delphi I want use function from this dll. How I can do it?

And other quastion I know function in C++_ (found in the internet)

M
1.439 Beiträge seit 2005
vor 14 Jahren

[DllImport(@"C:\CamUsb_API.dll", EntryPoint = "CamUSB_GetErrorString")]
static extern intGetErrorString(StringBuilder buffer, int maxLen, int errCode); 

StringBuilder buffer = new StringBuilder(256);
GetErrorString(buffer, buffer.Capacity, errorid);

F
28 Beiträge seit 2009
vor 14 Jahren

Hi,

probiers mal mit unsafe, hier kannst du pointer übernehmen.

Hier ein beispiel wie ich es aktuell mit ftdi mache:


// die DLL Definition
FT_STATUS FT_Read (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpdwBytesReturned)

// UCHAR Unsigned char (1 byte)
// PUCHAR Pointer to unsigned char (4 bytes)
// PCHAR Pointer to char (4 bytes) 
// DWORD Unsigned long (4 bytes)
// LPDWORD Pointer to unsigned long (4 bytes) 
// FT_HANDLE DWORD


// wird so eingebunden

[DllImport(FTD2XX.dll)]
static extern unsafe FT_STATUS FT_Read(FT_HANDLE ftHandle, void* lpBuffer, UInt32 dwBytesToRead, ref UInt32 lpdwBytesReturned);

// so verwendet in der methode
cBuf = new Byte[_BufferINLenght];

fixed (byte* pBuf = cBuf)
{                        
      ftStatus = FT_Read(currentOpenPort, pBuf, _BufferINLenght, ref RxdwRet);                      
}

// pBuf liefert einen pointer zu einem Byte Array


vielleicht hilft dir das weiter

I
ibuddy Themenstarter:in
16 Beiträge seit 2009
vor 14 Jahren

@marsgk: juhu, das hat funktioniert. ich habs wohl nicht so mit den datentypen .... mist

@FatToni: das hatte ich auch mal in betracht gezogen, aber ich hatte es mit dem marshallen gemacht ... weil unsafe ist ja nicht so der knüller und habe etwa 1000mal gelesen, dass man es in 99% der Fälle vermeiden kann. hab trotzdem vielen Dank für deine Hilfe!

Danke an alle!

_Help me work with library. I have dll library wrotre on Delphi I want use function from this dll. How I can do it?

And other quastion I know function in C++_ (found in the internet)

M
1.439 Beiträge seit 2005
vor 14 Jahren

@FatToni
Man braucht weder in deinem, noch in ibuddy Fall unsafe oder pointer.
In deinem Fall tut es ein einfaches byte-Array.

I
ibuddy Themenstarter:in
16 Beiträge seit 2009
vor 14 Jahren

mal noch ne andere frage:

ich muss etliche struct (für ein paar funktionen) erstellen, darin kommen unter anderem arrays mit fester größe drin vor, die ich aber ohne leeren konstruktor nicht erstellen kann. ich weiß noch, dass sich ein struct in c++ wie eine klasse verhielt (wenn man von den zugriffrechte auf eigenschaften absieht). in c# sind das aber zwei "ganz" unterschiedliche, sagen wir mal: unterschiedlichere Dinge?

so wie ich es verstehe, halten die structs hauptsächlich daten. die muss ich dann vorher auch irgendwie initialisieren, ergo, das ganze zeug kommt hinterher in eine übergeordnete klasse, zb "CamEinstellung".

kann ich denn auch klassen erstellen und die dann per marshallen an die dll-funktionen übergeben? wenn ja, wie? wenn nicht, wie mache ich das mit den arrays?

Über ein paar Ratschläge würde ich mich sehr freuen .... halt abgucken von den profis!

thx a lot!

ibuddy

_Help me work with library. I have dll library wrotre on Delphi I want use function from this dll. How I can do it?

And other quastion I know function in C++_ (found in the internet)

M
1.439 Beiträge seit 2005
vor 14 Jahren

=>MarshalAs-Attribut mit UnmanagedType.ByValArray

I
ibuddy Themenstarter:in
16 Beiträge seit 2009
vor 14 Jahren

ui, des war mir zu hoch!

kann ich mit UnmanagedType.ByValArray eine class als struct in dll verkaufen??

kann ich denn generell alle structs als class ethablieren? muss ich irgendetwas beachten?

bitte ein wenig ausführlicher. bitte soviel, dass es die suche nach ner lösung verkürzt ... 😄

wäre für ein minimalbsp. dankbar!

_Help me work with library. I have dll library wrotre on Delphi I want use function from this dll. How I can do it?

And other quastion I know function in C++_ (found in the internet)

F
10.010 Beiträge seit 2004
vor 14 Jahren

bitte soviel, dass es die suche nach ner lösung verkürzt ... 😄

[Hinweis] Wie poste ich richtig? Punkt 4c
Wenn du das suchen nach stichworten nicht hinbekommst, wird es in der Zukunft schwer

I
ibuddy Themenstarter:in
16 Beiträge seit 2009
vor 14 Jahren

Hallo FZelle,

es war nicht meine Absicht eine fertige Lösung zu erhalten. Ich bin nicht so sehr warm, dass ich weiß, wie jetzt genau was bei welchen Dingen abläuft. Ich wollte nur eine kurze methodische Herangehensweise wissen.
hatte gehofft, dass mir einer sagt, dass ist richtig, wie ich denke, dann kann ich auch in die richtung weiterüberlegen. odern halt nicht und dan vielleicht warum.

ich hatte mir jetzt überlegt, diese Struktur


        [StructLayout(LayoutKind.Sequential)]
        public class S_RESOLUTION_PARAMS
        {
            public sbyte wOffsetX;       // i16 X offset of ROI (relative to visible area). 
            public sbyte wOffsetY;       // i16 Y offset of ROI (relative to visible area). 
            public ushort wSizeX;         // u16 X size (width, columns) of ROI. 
            public ushort wSizeY;         // u16 Y size (height, lines) of ROI. 
            public uint dwSkip;         // u32 X- and Y- Skip Settings (see XY_SKIP_NONE). 
            public uint dwBin;          // u32 X- and Y- Bin Settings (see XY_BIN_NONE). 
            public sbyte bKeepExposure;  // u08 keep constant exposure (true=yes, false=no)
            public sbyte[] bReserved = new sbyte[3]; //  u08  bReserved [3] :reserved, keep 32-bit alignment  
        };

zu definieren und beim DllImport entsprechend mit UnmanagedType.ByValArray vorzugehen, a la


[DllImport(@"c:\Programme\ABS GmbH\UK3000\SDK\CamUsb_API.dll", EntryPoint = "CamUSB_GetImage")]
public static extern bool GetImage([MarshalAs(UnmanagedType.ByValArray)] S_RESOLUTION_PARAMS structure);                 

es ging mir nur ums prinzipielle. Wollte keinem auf n schlipps treten. ich entschuldige mich für meine unsicherheit in diesen Belangen!

Viele Grüße,
ibuddy

_Help me work with library. I have dll library wrotre on Delphi I want use function from this dll. How I can do it?

And other quastion I know function in C++_ (found in the internet)

M
1.439 Beiträge seit 2005
vor 14 Jahren

Das [MarshalAs(UnmanagedType.ByValArray)] musst du auf das Array im struct anwenden.
Zeig einfach mal die Header-Datei her, dann kann man dir besser helfen.

I
ibuddy Themenstarter:in
16 Beiträge seit 2009
vor 14 Jahren

Hallo marsgk,

danke für deine antwort. in der header-datei steht zum struct


typedef struct
{
	i16		wOffsetX;				//!< X offset of ROI (relative to visible area)
	i16		wOffsetY;				//!< Y offset of ROI (relative to visible area)
	u16		wSizeX;					//!< X size (width, columns) of ROI
	u16		wSizeY;					//!< Y size (height, lines) of ROI

	u32		dwSkip;					//!< X- and Y- Skip Settings (see #XY_SKIP_NONE)
	u32		dwBin;					//!< X- and Y- Bin Settings (see #XY_BIN_NONE)
	u08		bKeepExposure;			//!< keep constant exposure (true=yes, false=no)
	u08		bReserved[3];			//!< reserved, keep 32-bit alignment
} S_RESOLUTION_PARAMS, S_RESOLUTION_RETVALS;

Wenn ich dich richtig verstehe, dann müsste die Definition etwa wie folgt lauten:


        [StructLayout(LayoutKind.Sequential)] // event. in der dllimport dann als "[in,out] S_RESOLUTION_PARAMS ResParam" aufrufen
        public class S_RESOLUTION_PARAMS
        {
            public sbyte wOffsetX;       // i16 X offset of ROI (relative to visible area). 
            public sbyte wOffsetY;       // i16 Y offset of ROI (relative to visible area). 
            public ushort wSizeX;         // u16 X size (width, columns) of ROI. 
            public ushort wSizeY;         // u16 Y size (height, lines) of ROI. 
            public uint dwSkip;         // u32 X- and Y- Skip Settings (see XY_SKIP_NONE). 
            public uint dwBin;          // u32 X- and Y- Bin Settings (see XY_BIN_NONE). 
            public sbyte bKeepExposure;  // u08 keep constant exposure (true=yes, false=no)
            [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
            public sbyte[] bReserved; //  u08  bReserved [3] :reserved, keep 32-bit alignment  
        };

[...]

//Aufruf:

[DllImport(@"c:\Programme\ABS GmbH\UK3000\SDK\CamUsb_API.dll", EntryPoint = "CamUSB_GetImage")]
public static extern bool GetImage(     S_RESOLUTION_PARAMS structure     );

Mal nebenbei, kannst du mir oder jemand anderes sagen, was bei dieser ( <<-------) C++-Zeile passiert? Ist aus einem Beispiel-Code zur Applikation und ich hab keine ahnung


ULONGLONG qwFunctionMask;
DWORD     dwCapSize;
S_RESOLUTION_CAPS   *pResCap   = NULL;

// FUNC_RESOLUTION = 0 is constant

[....]

// ---- get resolution cap
if (qwFunctionMask & FUNC_RESOLUTION == FUNC_RESOLUTION)
{
  CamUSB_GetFunctionCaps( FUNC_RESOLUTION, NULL, &dwCapSize );
  pResCap = (S_RESOLUTION_CAPS*) new (BYTE[dwCapSize]);                <<-------
  CamUSB_GetFunctionCaps( FUNC_RESOLUTION, (PVOID) pResCap, &dwCapSize );
}

Mit CamUSB_GetFunctionCaps wird lediglich geprüft, welche Funktionen von der Kamera unterstützt werden.

Hab vielen Dank für deine/eure Hilfe!

Viele Grüße,
ibuddy

_Help me work with library. I have dll library wrotre on Delphi I want use function from this dll. How I can do it?

And other quastion I know function in C++_ (found in the internet)

S
248 Beiträge seit 2008
vor 14 Jahren

Hallo ibuddy,

von den Namen der Datentypen her würde ich die Klasse so definieren:

        [StructLayout(LayoutKind.Sequential, Size = 20)] // event. in der dllimport dann als "[in,out] S_RESOLUTION_PARAMS ResParam" aufrufen
        public class S_RESOLUTION_PARAMS
        {
            public short wOffsetX;       // i16 X offset of ROI (relative to visible area).
            public short wOffsetY;       // i16 Y offset of ROI (relative to visible area).
            public ushort wSizeX;         // u16 X size (width, columns) of ROI.
            public ushort wSizeY;         // u16 Y size (height, lines) of ROI.
            public uint dwSkip;         // u32 X- and Y- Skip Settings (see XY_SKIP_NONE).
            public uint dwBin;          // u32 X- and Y- Bin Settings (see XY_BIN_NONE).
            public byte bKeepExposure;  // u08 keep constant exposure (true=yes, false=no)
        };

Durch die Angabe der absoluten Größe kannst du das Array weglassen (welches eh nur fürs Alignment ist).

Zu der C++ Anweisung:
"pResCap = (S_RESOLUTION_CAPS*) new (BYTE[dwCapSize]);"

In C++ kannst du Speicher mit dem new Operator allokieren. In dem Fall wird ein byte-array der Größe "dwCapSize" allokiert. Durch den Cast (S_RESOLUTION_CAPS*) kann nun der Speicher so verwendet werden, als sei es ein Array von "S_RESOLUTION_CAPS".
new

Spooky

I
ibuddy Themenstarter:in
16 Beiträge seit 2009
vor 14 Jahren

Hallo Spook,

vielen Dank für deine Antwort. Ich hab mit den Herstellern gesprochen und die meinten, dass die Arrays dafür seien, erst zur Laufzeit feststehende Arrays aufzunehmen .... naja, er meinte, es gäbe noch andere Mittel und Wege: Über andere Funktionen, die ich vorher nicht kannte und der Hersteller bereitstellt.

Ich habe aber nu ein anderes kleines Problem: Ich lese mit folgendem Code ein Bild von der Kamera:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

(...)

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class S_CAMERA_HEADER
        {
            ushort wStatus;         // u16 unused 
            short wBlock_id;        // u16 unused 
            byte bPacket_format;    // u08 format of packet 
            byte bPacket_id_high;   // u08 packet id high part 
            ushort wPacket_id_low;  // u16 packet id low part 
            ushort wReserved1;      // u16 unused 
            ushort wPayload_type;   // u16 packet payload type 
            uint dwTimestamp_high;  // u32 timestamp high dword see dwTimestamp_low 
            uint dwTimestamp_low;   // u32 timestamp low dword
            uint dwPixel_type;      // u32 pixel type (see Pixeltypes ) 
            uint dwSize_x;          // u32 horizontal (x) size 
            uint dwSize_y;          // u32 vertical (y) size 
            int dwOffset_x;         // i32 horizontal (x) offset 
            int dwOffset_y;         // i32 vertical (y) offset
        };

(...)

        [DllImport(@"c:\Programme\ABS GmbH\UK3000\SDK\CamUsb_API.dll", EntryPoint = "CamUSB_GetImage", CharSet=CharSet.Auto)]
        public static extern bool GetImage(
                                            ref IntPtr ppImageBuffer,           // LPBYTE *  ppImageBuffer,
                                            ref S_CAMERA_HEADER ppImageHeader,  // S_IMAGE_HEADER **  ppImageHeader,  
                                            uint dwImageBufSize                 // DWORD  dwImageBufSize = 0,  
                                            //byte ndev,                        // BYTE  nDevNr = 0,  
                                            //ulong dwTimeout                   // DWORD  dwTimeout = GETIMAGE_DEFAULT_TIMEOUT  = 0  
                                            );

(...)


        static void Main(string[] args)
        {

(...)

// Bild von der Kamera ziehen
            uint SizeOfBuffer = 1360 * 1024;
            byte[] picBuffer = new byte[SizeOfBuffer];
            //  string picBuffer;
            S_CAMERA_HEADER Header = new S_CAMERA_HEADER();

            IntPtr pBuffer = Marshal.AllocHGlobal((int) SizeOfBuffer);

            if (GetImage(ref pBuffer, ref Header, SizeOfBuffer))
            {
                Console.WriteLine("Alles Super");
            }
            else
            {
                Console.WriteLine("Nix mit Bild, du Konk!");
            }

            // Speicherinhalt in ein Byte-Array kopieren

// Variante 1 -------------------

            byte[] pic = new byte[SizeOfBuffer];
            Marshal.Copy(pBuffer, pic, 0, pic.Length);

// Variante 1 -------------------



/*// Variante 2 -------------------
  
            // Speicher lesen und in Byte-Array lesen
            byte[] pic = new byte[SizeOfBuffer];
            for (int pos = 0; pos < SizeOfBuffer; pos++)
            {
                pic[pos] = Marshal.ReadByte(pBuffer, pos);
            }
  
// Variante 2 -------------------*/

            Marshal.FreeHGlobal(pBuffer);  // free pointer 

(...)
            string wait = Console.ReadLine();
        }

Mein Problem ist gerade nicht, dass es nicht funktioniert, sondern, dass wenn ich dann nach dem Durchlaufen Enter drücke, schließt sich das cmd-fenster nicht sofort. Es dauer mehr als 10 Sekunden. Ich habe keine Ahnung woran das liegt. Vielleicht am Speicher allokieren und wieder freigeben oder was .... ach, ich hab echt keinen schimmer.

Hat jemand ne Ahnung und kann helfen?

Vielen Dank für jede Hilfe!

Viele Grüße, ibuddy

_Help me work with library. I have dll library wrotre on Delphi I want use function from this dll. How I can do it?

And other quastion I know function in C++_ (found in the internet)

F
28 Beiträge seit 2009
vor 14 Jahren

@ibuddy, @marsgk, Ihr habt recht ein einfaches byte array tuts auch, funktioniert wunderbar und auf unsafe kann ich auch verzichten...

für alle die es interessiert:


[DllImport(FtdiDLLFile)]
static extern FT_STATUS FT_Read(FT_HANDLE ftHandle, byte[] lpBuffer, UInt32 dwBytesToRead, ref UInt32 lpdwBytesReturned);  // nun mit byte[]


// und so in der methode
ftStatus = FT_GetQueueStatus(currentOpenPort, ref RxBytes);
cBuf = new Byte[RxBytes];                    
ftStatus = FT_Read(currentOpenPort, cBuf, RxBytes, ref RxdwRet);                                                            



thanks
Fattoni

L
1 Beiträge seit 2010
vor 14 Jahren

Mein Problem ist gerade nicht, dass es nicht funktioniert, sondern, dass wenn ich dann nach dem Durchlaufen Enter drücke, schließt sich das cmd-fenster nicht sofort. Es dauer mehr als 10 Sekunden. Ich habe keine Ahnung woran das liegt. Vielleicht am Speicher allokieren und wieder freigeben oder was .... ach, ich hab echt keinen schimmer.

Wahrscheinlich wurde die Kamera nicht mit CamUSB_FreeCamera freigegeben...