Marshalling struct containing an enum in C# -
brief : have got .dll function i'm trying use in c# application. 1 of function doesn't work , returns "invalid arguments" status.
i guessed marshalling issue.
here .dll header :
typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned long long uint64; typedef signed char int8; typedef signed short int16; typedef signed long long int64; #ifndef _msc_ver typedef unsigned char bool; #endif #ifdef __x86_64__ typedef unsigned int uint32; typedef signed int int32; #else typedef unsigned long uint32; typedef signed long int32; #endif typedef enum i2c_clockrate_t{ i2c_clock_standard_mode = 100000, /* 100kb/sec */ i2c_clock_fast_mode = 400000, /* 400kb/sec */ i2c_clock_fast_mode_plus = 1000000, /* 1000kb/sec */ i2c_clock_high_speed_mode = 3400000 /* 3.4mb/sec */ }i2c_clockrate; /* channel configuration information */ typedef struct channelconfig_t { i2c_clockrate clockrate; uint8 latencytimer; uint32 options; }channelconfig; /******************************************************************************/ /******************************************************************************/ /* function declarations */ /******************************************************************************/ ftdi_api ft_status i2c_getnumchannels(uint32 *numchannels); ftdi_api ft_status i2c_getchannelinfo(uint32 index, ft_device_list_info_node *chaninfo); ftdi_api ft_status i2c_openchannel(uint32 index, ft_handle *handle); ftdi_api ft_status i2c_initchannel(ft_handle handle, channelconfig *config); ftdi_api ft_status i2c_closechannel(ft_handle handle); ftdi_api ft_status i2c_deviceread(ft_handle handle, uint32 deviceaddress, uint32 sizetotransfer, uint8 *buffer, uint32 *sizetransfered, uint32 options); ftdi_api ft_status i2c_devicewrite(ft_handle handle, uint32 deviceaddress, uint32 sizetotransfer, uint8 *buffer, uint32 *sizetransfered, uint32 options); ftdi_api void init_libmpsse(void); ftdi_api void cleanup_libmpsse(void); ftdi_api ft_status ft_writegpio(ft_handle handle, uint8 dir, uint8 value); ftdi_api ft_status ft_readgpio(ft_handle handle,uint8 *value);
so i've made c# wrapper use functions :
#region declaration of general drivers methods /// <summary> /// function gets number of i2c channels connected host system. number of ports available in each of these chips different. /// </summary> /// <param name="numchannels">the number of channels connected host</param> /// <returns>returns status code of type ft_status</returns> [dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_getnumchannels( ref uint numchannels ); /// <summary> /// function takes channel index (valid values 0 value returned i2c_getnumchannels – 1 ) , provides information channel in form of populated ft_device_list_info_node structure /// </summary> /// <param name="index">index of channel </param> /// <param name="chaninfo">pointer ft_device_list_info_node structure</param> /// <returns>returns status code of type ft_status</returns> [dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_getchannelinfo( uint index, ref ftdi.ft_device_info_node chaninfo ); /// <summary> /// function opens indexed channel , provides handle it. valid values index of channel can 0 value obtained using i2c_getnumchannels – 1). /// </summary> /// <param name="index">index of channel</param> /// <param name="handle">pointer handle of type ft_handle</param> /// <returns>returns status code of type ft_status</returns> [dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_openchannel( uint index, ref ulong handle ); /// <summary> /// function initializes channel , communication parameters associated it. /// </summary> /// <param name="handle">handle of channel </param> /// <param name="config">pointer channelconfig structure. members of channelconfig structure contains values i2c master clock, latency timer , options</param> /// <returns>returns status code of type ft_status</returns> [dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_initchannel( ulong handle, [marshalas(unmanagedtype.struct)] ref c_types.channelconfig config ); /// <summary> /// closes channel , frees resources used /// </summary> /// <param name="handle">handle of channel </param> /// <returns>returns status code of type ft_status</returns> [dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_closechannel( ulong handle ); /// options summary /// parameter specifies data transfer options. bit positions defined each of these options are: /// bit0: if set start condition generated in i2c bus before transfer begins. bit mask defined options in file ftdi_i2c.h i2c_transfer_options_start_bit /// bit1: if set stop condition generated in i2c bus after transfer ends. bit mask defined options in file ftdi_i2c.h i2c_transfer_options_stop_bit /// bit2: reserved (only used in i2c_devicewrite) /// bit3: i2c slaves require i2c master generate nak last data byte read. setting bit enables working such i2c slaves. bit mask defined bit i2c_transfer_options_nack_last_byte /// bit4: setting bit invoke multi byte i2c transfer without having delays between start, address, data , stop phases. size of transfer in parameters sizetotransfer , sizetransfer red in bytes. bit mask defined bit i2c_transfer_options_fast_transfer_bytes* /// bit5: setting bit invoke multi bit transfer without having delays between start, address, data , stop phases. size of transfer in parameters sizetotransfer , sizetransfer red in bytes. bit mask defined bit i2c_transfer_options_fast_transfer_bits* /// bit6: deviceaddress parameter ignored if bit set. feature may useful in generating special i2c bus conditions not require address passed. setting bit effective when either 2c_transfer_options_fast_transfer_bytes or i2c_transfer_options_fast_transfer_bits set. bit mask defined bit i2c_transfer_options_no_address* /// bit7–bit31:reserved /// more information see an_177_user_guide_for_libmpsse-i2c.pdf /// <summary> /// function reads specified number of bytes addressed i2c slave /// </summary> /// <param name="handle">handle of channel </param> /// <param name="deviceaddress">address of i2c slave. 7bit value , should not contain data direction bit, i.e. decimal value passed should less 128</param> /// <param name="sizetotransfer">number of bytes read </param> /// <param name="buffer">pointer buffer data read</param> /// <param name="sizetransfered">pointer variable containing number of bytes read</param> /// <param name="options">cf options</param> /// <returns>returns status code of type ft_status</returns> [dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_deviceread( ulong handle, uint deviceaddress, uint sizetotransfer, ref byte buffer, ref uint sizetransfered, uint options ); /// <summary> /// function writes specified number of bytes addressed i2c slave. /// </summary> /// <param name="handle">handle of channel</param> /// <param name="deviceaddress">address of i2c slave. 7bit value , should not contain data direction bit, i.e. decimal value passed should less 128</param> /// <param name="sizetotransfer">number of bytes written</param> /// <param name="buffer">pointer buffer data written</param> /// <param name="sizetransfered">pointer variable containing number of bytes written</param> /// <param name="options">cf options</param> /// <returns></returns> [dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_devicewrite( ulong handle, uint deviceaddress, uint sizetotransfer, ref byte[] buffer, ref uint sizetransfered, uint options ); #endregion
i have managed use i2c_getnumchannels, i2c_openchannel , i2c_closechannel functions stucked on i2c_initchannel.
reminder :
.dll :
ftdi_api ft_status i2c_initchannel(ft_handle handle, channelconfig *config);
wrapper :
[dllimport("libmpsse.dll", setlasterror = true, charset = charset.auto)] public extern static ftdi.ft_status i2c_initchannel( ulong handle, [marshalas(unmanagedtype.struct)] ref c_types.channelconfig config );
here c# structure implementation :
/// <summary> /// i2c clockrate enum pc i2c connection /// </summary> public enum i2c_clockrate { i2c_clock_standard_mode = 100000, /* 100kb/sec */ i2c_clock_fast_mode = 400000, /* 400kb/sec */ i2c_clock_fast_mode_plus = 1000000, /* 1000kb/sec */ i2c_clock_high_speed_mode = 3400000 /* 3.4mb/sec */ }; /// <summary> /// channel configuration information pc i2c connection /// </summary> [structlayout(layoutkind.sequential)] public struct channelconfig { public i2c_clockrate clockrate; public byte latencytimer; public uint options; public channelconfig(i2c_clockrate pclockrate, byte platencytimer, uint poptions) { clockrate = pclockrate; latencytimer = platencytimer; options = poptions; } public channelconfig(i2c_clockrate pclockrate, byte platencytimer) { clockrate = pclockrate; latencytimer = platencytimer; options = 0x00000000; } }
the problem dll function return _ftstatus saying : "invalid arguments".
i'm guessing because did not marshalled function can't figure error be.
Comments
Post a Comment