Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I write VB.NET class for implement CH341DLL.DLL functionality. The method
CH341StreamI2C()
is used for stream write and read into device. This way I've imported the method
CH341StreamI2C()
from DLL:
<DllImport("CH341DLL.DLL", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)>
Private Shared Function CH341StreamI2C(ByVal iIndex As Integer, ByVal iWriteLength As Integer, ByRef iWriteBuffer As IntPtr, ByVal iReadLength As Integer, ByRef oReadBuffer As IntPtr) As Boolean
End Function
For check how this method works, I use I2C humidity and temperature sensor HTU21D. It's IIC address is 40h, and register where temperature is getting is E3h. So I invoke method CH341StreamI2C() like this:
Dim writeBuffer as Byte() = {&H40, &hE3} 'Address+Command
Dim s As String = Encoding.Unicode.GetString(writeBuffer)
Dim writeBufPtr As IntPtr = Marshal.StringToHGlobalAuto(s) 'Get pointer for write buffer
Dim wLen As Integer = writeBuffer.Length
Dim readBufPtr As IntPtr = IntPtr.Zero 'Init read pointer
Dim rLen as Integer = 3 'Sensor must return 3 bytes
Dim res As Boolean = CH341StreamI2C(0, wLen, writeBufPtr, rLen, readBufPtr)
I use logic analyzer to see what is on the SDA and SCL lines. And result is unpredictable. For example, if call previous code 4 times, that's the result:
It's seen, that physically CH341 device writes unpredictable values in the line. This is not DLL error, because other applications use this method and the result is correct. For note, other methods, e.g. CH341ReadI2C() and CH341WriteI2C(), that reads/writes only one byte per time, acts correct in my code.
What is the probably reason of the such behavior? May be, I've marshalled write buffer incorrect? How is the right way to do this?
–
–
If this is what you're using, the original declaration is:
BOOL WINAPI CH341StreamI2C(ULONG iIndex, ULONG iWriteLength, PVOID iWriteBuffer, ULONG iReadLength, PVOID oReadBuffer);
Since the buffer parameters are PVOID
s, you should be able to just marshal them directly to byte arrays:
<DllImport("CH341DLL.DLL", SetLastError:=True, CallingConvention:=CallingConvention.StdCall)>
Private Shared Function CH341StreamI2C(ByVal iIndex As Integer, ByVal iWriteLength As Integer, ByVal iWriteBuffer As Byte(), ByVal iReadLength As Integer, ByVal oReadBuffer As Byte()) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Arrays are reference types (classes) which means you always refer to them via their memory pointer. Thus when you pass them to a function (P/Invoked or not) you're actually passing the array's pointer, rather than the array itself. This is really helpful when P/Invoking since it often lets you pass the arrays as-is.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.