There is a dll written in c ++. You must use it in c #. heder c ++

//--------------------------------------------------------------------------- #ifndef CRZUSBH #define CRZUSBH //--------------------------------------------------------------------------- #ifdef CRZUSB_EXPORTS #define CRZUSB_API extern "C" __declspec(dllexport) #else #define CRZUSB_API extern "C" __declspec(dllimport) #endif //--------------------------------------------------------------------------- #define SIZE_MATR_ADDR_RECV 512 #define MAX_COUNT_RZ_DATA 128 #define MAX_COUNT_CHANNELS 16 #define FREQ_RZ_GET_DEVICE 0x00 #define FREQ_RZ_12and5kHz 0x01 #define FREQ_RZ_50kHZ 0x02 #define FREQ_RZ_100kHZ 0x03 #define FREQ_RZ_UNKNOWN 0xFF #define FORMAT_RZ_DOP 0x00 #define FORMAT_RZ_OSN 0x01 #define CTRL_PARR_PARITY 0x00 #define CTRL_PARR_ODDNESS 0x01 #define IDDEV_2RZTOUSB 0x01 #define ENABLE_ADDR_REC 0x01 #define DISABLE_ADDR_REC 0x00 //--------------------------------------------------------------------------- //#pragma pack(show) #pragma pack(push,1) //#pragma pack(show) struct sInitDevice { unsigned char ucFreqRZ; unsigned char ucFormatRZ; unsigned char ucCtrlParr; unsigned char ucAddrRecv; unsigned char pucMatrAddrRecv[SIZE_MATR_ADDR_RECV]; }; struct sInitDeviceEx { struct sInitChannel { BYTE FreqRZ; BYTE FormatRZ; BYTE CtrlParr; } ParamChannel[MAX_COUNT_CHANNELS]; BYTE AddrRecv; BYTE MatrAddrRecv[SIZE_MATR_ADDR_RECV]; }; struct sInfoDevice { bool bCorrectInfo; unsigned char ucCodeErrorDevice; unsigned char ucIDDevice; unsigned char ucFreqRZ; unsigned char ucCountChannels; unsigned short usDensityRZ; unsigned short usPlantNum; unsigned short usNumPO; unsigned short usVersionPO; }; struct sInfoDeviceEx { bool bCorrectInfo; BYTE CodeErrorDevice; BYTE IDDevice; WORD NumPO; WORD VersionPO; WORD PlantNum; BYTE CountChannels; struct sInfoChannel { BYTE FreqRZ; WORD DensityRZ; } InfoChannel[MAX_COUNT_CHANNELS]; }; struct sRZStream { unsigned char CountRZMessage; unsigned short CountTrashRZMessage; unsigned short CountMissingRZMessage; bool IsMissingRZMessage; struct { unsigned char Address; unsigned char Low; unsigned char High; unsigned char Additional; unsigned char Channel; } RZ_DATA[MAX_COUNT_RZ_DATA]; //Index RZ_DATA: [0 ... (CountRZMessage - 1)] }; struct sRZStreamEx { struct { union { struct { BYTE Low; BYTE High; BYTE Additional; BYTE Address; }; DWORD RzMessage; }; } RZ_DATA[MAX_COUNT_RZ_DATA]; struct { BYTE Channel_0 : 4; BYTE Channel_1 : 4; } CHANNELS[MAX_COUNT_RZ_DATA / 2]; BYTE System00; BYTE CountRZMessage; union { struct { BYTE CountTrashRZMessageL; BYTE CountTrashRZMessageH; }; WORD CountTrashRZMessage; }; BYTE IsMissingRZMessage; union { struct { BYTE CountMissingRZMessageL; BYTE CountMissingRZMessageH; }; WORD CountMissingRZMessage; }; BYTE System07; BYTE System08; BYTE System09; BYTE System10; BYTE System11; BYTE System12; BYTE System13; BYTE System14; BYTE System15; inline BYTE GetChannelRZMessage (int IndexRZMessage) { return (IndexRZMessage & 0x01) ? CHANNELS[IndexRZMessage >> 1].Channel_1 : CHANNELS[IndexRZMessage >> 1].Channel_0; } }; struct sRZTimingData { BYTE Data[MAX_COUNT_RZ_DATA]; }; #pragma pack(pop) //#pragma pack(show) //--------------------------------------------------------------------------- CRZUSB_API bool RzUsb_ConnectDevice (void); CRZUSB_API bool RzUsb_IsConnectToDevice (void); CRZUSB_API bool RzUsb_DisconnectDevice (void); CRZUSB_API bool RzUsb_InitDevice (sInitDevice*, sInfoDevice*); CRZUSB_API bool RzUsb_InitDeviceEx (sInitDeviceEx*, sInfoDeviceEx*); CRZUSB_API void RzUsb_SetReadTimeout (unsigned long); CRZUSB_API void RzUsb_SetWriteTimeout (unsigned long); CRZUSB_API bool RzUsb_RunReceiveRZ (void); CRZUSB_API bool RzUsb_StopReceiveRZ (void); CRZUSB_API bool RzUsb_ReceiveRZStream (sRZStream*); CRZUSB_API bool RzUsb_ReceiveRZStreamEx (sRZStreamEx*); CRZUSB_API bool RzUsb_IsReceiveRZStream (void); //--------------------SUPPORT TIMING DATA------------------------------------ CRZUSB_API bool RzUsb_IsSupportTimingData (void); CRZUSB_API bool RzUsb_GetTimingData (sRZTimingData*); //--------------------------------------------------------------------------- #endif //--------------------------------------------------------------------------- 

How to convert structures for with #?

  • one
    Making a simple marshaling - Ares

1 answer 1

It is like mixing managed and native code. In this case, COM objects are well integrated into C #. Therefore, one of the integration methods is to create a binding in the form of a COM object. In this case, the dll data can be converted to data that is understandable in managed code.

Another way (I like it more) is to use C ++ CLR. To do this, create a project of type Class Library and in it a CLR class that will manage the native dll. Here, too, data will have to be converted, but this can be done in the form of the same CLR objects.

Below, I wrote a small code for example. I in it load library of work with a socket.

 #pragma once #include "windows.h" #include <atlstr.h> using namespace System; namespace NativeClasses { public ref class AddrIn { public: int Port; String^ sAddr; }; public ref class NativeSocket { u_short (*htons)(u_short); unsigned long (*inet_addr)(const char*); public: NativeSocket(void) { HMODULE hm = LoadLibrary (L"ws2_32.dll"); if ( hm ) { SOCKET (*socket)(int,int,int) = (SOCKET (*)(int,int,int)) GetProcAddress(hm, "socket"); int (*closesocket)(SOCKET) = (int (*)(SOCKET)) GetProcAddress(hm, "socket"); htons = (u_short (*)(u_short)) GetProcAddress(hm, "htons"); inet_addr = (unsigned long (*)(const char*)) GetProcAddress(hm, "inet_addr"); SOCKET s = (*socket) (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s) (*closesocket) (s); FreeLibrary(hm); } } void SetAddr( AddrIn^ Addr ) { sockaddr_in addr = {0}; addr.sin_family = AF_INET; addr.sin_port = (*htons)(Addr->Port); CString sAddr(Addr->sAddr); CW2A asAddr(sAddr); addr.sin_addr.S_un.S_addr = (*inet_addr)(asAddr); } }; } 

An assembly with classes is then included in the project references in C # and can be used by a regular call:

 NativeClasses.NativeSocket s = new NativeClasses.NativeSocket(); NativeClasses.AddrIn addr = new NativeClasses.AddrIn() ; addr.Port = 1000; addr.sAddr = "10.1.0.100"; s.SetAddr(addr); 

In my opinion, it’s best to use ATL to convert strings. The rest is at the discretion.