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)
[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);
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
@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)
@FatToni
Man braucht weder in deinem, noch in ibuddy Fall unsafe oder pointer.
In deinem Fall tut es ein einfaches byte-Array.
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)
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)
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
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)
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.
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)
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
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)
@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
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...