473,385 Members | 1,727 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Marshaling data between managed VB.NET and an unmanaged C Dll

Hello,
I am trying to get some data from a C Dll via a structure and I am getting incorrect values back. I tried a couple of examples I found but they do not work. Since I do not know the proper way. I do not know how to fix it. Can anyone give me any advice, hints, redirection or any assistance what-so-ever. I've been struggling with this for weeks now so I will appreciate any kind of guidance (so will my boss :).
Feb 18 '10 #1

✓ answered by MarDude

I found out that a pointer to a structure is not the same as a pointer to the memory that the structure occupies. Changed my code to copy the members explicitly.
Expand|Select|Wrap|Line Numbers
  1.         Dim rc As twRC
  2.         Dim pOneValue As IntPtr
  3.         Dim pPosition As Int32 = 0
  4.         Dim strValue As String
  5.         Dim twFix32 As twsFix32
  6.         Dim twOneValue As TW_ONEVALUE
  7.  
  8.  
  9.         rc = DS_Capability(mtwApp, mtwSource, twDG.Control, twDAT.Capability, twMSG.Get, twCapability)
  10.         If rc = twRC.Success Then
  11.  
  12.             twOneValue = New TW_ONEVALUE
  13.             pOneValue = GlobalLock(twCapability.Handle)
  14.             twOneValue.ItemType = CType(Runtime.InteropServices.Marshal.ReadInt16(pOneValue, pPosition), ItemType)
  15.             pPosition += 2
  16.  
  17.             Select Case twOneValue.ItemType
  18.  
  19.                 Case ItemType.Fix32
  20.                     Dim origFrac As Int32
  21.                     twFix32 = New twsFix32
  22.  
  23.                     twOneValue.Item = Marshal.ReadInt16(pOneValue, pPosition)
  24.                     twFix32.Whole = twOneValue.Item
  25.                     pPosition += 2
  26.  
  27.  
  28.                     origFrac = Marshal.ReadInt16(pOneValue, pPosition)
  29.                     If origFrac < 0 Then
  30.                         origFrac += 65536
  31.                     End If
  32.                     pPosition += 2
  33.  
  34.                     'twFix32.Frac = CUShort(origFrac)
  35.                     strValue = (twFix32.Whole + (origFrac / 65536)).ToString
  36.  
  37.                 Case Else
  38.                     MsgBox("Unexpected One Value.  Ignored")
  39.  
  40.             End Select
  41.  
  42.             GlobalUnlock(twCapability.Handle)
  43.  
  44.             Return strValue
  45.  
  46.         End If

3 5310
tlhintoq
3,525 Expert 2GB
Another post here on Bytes for nearly the same thing.
http://bytes.com/topic/net/answers/8...-through-dll-c

Hint: There is a search box in the upper right of the Bytes webpage.
Feb 18 '10 #2
Thanks for the reply. For the record I searched through quite a few pages on this site which took a couple of hours and found NOTHING helpful. Perhaps no one used the same keywords I used, although it did pick up several quotes that contained the keywords which the article had no relation.
And that link you provided doesn't provide anything useful, besides it discusses C#, NOT VB. since the problem I am having involves passing data from one language to another, including a third unnecessarily complicates things. Perhaps I need to give more detailed information, here goes:

I am writing a VB.NET application that uses TWAIN (dumb dll). When I call the function and get data back it is incorrect. What I don't know is what I am doing wrong. Here are the C structures:
Expand|Select|Wrap|Line Numbers
  1. typedef unsigned short TW_UINT16, FAR *pTW_UINT16;
  2. typedef unsigned long  TW_UINT32, FAR *pTW_UINT32;
  3. typedef HANDLE         TW_HANDLE;
  4.  
  5. typedef struct {
  6.    TW_UINT16  Cap; /* id of capability to set or get, e.g. CAP_BRIGHTNESS */
  7.    TW_UINT16  ConType; /* TWON_ONEVALUE, _RANGE, _ENUMERATION or _ARRAY   */
  8.    TW_HANDLE  hContainer; /* Handle to container of type Dat              */
  9. } TW_CAPABILITY, FAR * pTW_CAPABILITY;
  10.  
  11. typedef struct {
  12.    TW_UINT16  ItemType;
  13.    TW_UINT32  Item;
  14. } TW_ONEVALUE, FAR * pTW_ONEVALUE;
  15.  
  16.  
Which have been converted to VB.NET structure/class:

Expand|Select|Wrap|Line Numbers
  1.     <StructLayout(LayoutKind.Sequential, Pack:=4)> Private Structure twsCapability
  2.         Public Cap As twCap         'short
  3.         Public ConType As twContainerTyoe   'short
  4.         Public Handle As IntPtr     'Pointer to a container
  5.     End Structure
  6.  
  7.     <StructLayout(LayoutKind.Sequential, Pack:=4)> Friend Class TW_ONEVALUE
  8.         Public ItemType As Short
  9.         Public Item As Integer
  10.     End Class
  11.  
Then I run this routine and get back 64356640 for the physical height and width:
Expand|Select|Wrap|Line Numbers
  1. 'Call into the C library
  2.     <DllImport("twain_32.dll", EntryPoint:="#1")> Private Shared Function DS_Capability( _
  3.         <[In](), Out()> ByVal pOrigin As twsIdentity, _
  4.         <[In]()> ByVal pSource As twsIdentity, _
  5.         ByVal dg As twDG, _
  6.         ByVal dat As twDAT, _
  7.         ByVal msg As twMSG, _
  8.         <[In](), Out()> ByRef pData As twsCapability) As twRC
  9.     End Function
  10.  
  11. 'Start here:
  12.             ...previous code
  13.             twCapability = New twsCapability
  14.             With twCapability
  15.                 .Cap = twCap.IPhysicalWidth
  16.                 .ConType = twContainerTyoe.One   'TWON_DONTCARE16
  17.                 '.Handle = Nothing
  18.             End With
  19.             strWidth = GetOneValue(twCapability)
  20.  
  21.             With twCapability
  22.                 .Cap = twCap.IPhysicalHeight
  23.                 '.ConType = 7 'TWON_DONTCARE16
  24.                 '.Handle = Nothing
  25.             End With
  26.             strHeight = GetOneValue(twCapability)
  27.             ...more code
  28.  
  29. Private Function GetOneValue(ByVal twCapability As twsCapability) As String
  30.  
  31.         Dim rc As twRC
  32.         Dim strTemp As String
  33.         Dim twOneValue As TW_ONEVALUE
  34.  
  35.  
  36.         rc = DS_Capability(mtwApp, mtwSource, twDG.Control, twDAT.Capability, twMSG.Get, twCapability)
  37.         If rc = twRC.Success Then
  38.             strTemp = vbNullString
  39.             Select Case twCapability.ConType
  40.                 Case twContainerTyoe.One
  41.                     twOneValue = New TW_ONEVALUE
  42.                     Marshal.PtrToStructure(twCapability.Handle, twOneValue)
  43.                     strTemp = CType(twOneValue.Item, String)
  44.                 Case Else
  45.                     MsgBox("Error, one value expected; " & twCapability.ConType & " returned.")
  46.             End Select
  47.             Marshal.FreeHGlobal(twCapability.Handle)
  48.             Return strTemp
  49.         Else
  50.             ErrorStatus()
  51.             Return vbNullString
  52.         End If
  53.  
  54.     End Function
  55.  
  56. Private Function GetOneValueNew(ByVal twCapability As twsCapability) As String
  57.  
  58.         Dim rc As twRC
  59.         Dim pOneValue As Integer
  60.         Dim pTemp As Integer
  61.         Dim strTemp As String
  62.         Dim twOneValue As TW_ONEVALUE
  63.  
  64.  
  65.         rc = DS_Capability(mtwApp, mtwSource, twDG.Control, twDAT.Capability, twMSG.Get, twCapability)
  66.         If rc = twRC.Success Then
  67.             strTemp = vbNullString
  68.             Select Case twCapability.ConType
  69.                 Case twContainerTyoe.One
  70.                     twOneValue = New TW_ONEVALUE
  71.                     pOneValue = GlobalLock(twCapability.Handle)
  72.                     pTemp = VarPtr(twOneValue)
  73.                     CopyMemory(pTemp, pOneValue, Marshal.SizeOf(twOneValue))
  74.                     GlobalUnlock(twCapability.Handle)
  75.                     strTemp = CType(twOneValue.Item, String)
  76.                 Case Else
  77.                     MsgBox("Error, one value expected; " & twCapability.ConType & " returned.")
  78.             End Select
  79.             GlobalFree(twCapability.Handle)
  80.             Return strTemp
  81.         Else
  82.             ErrorStatus()
  83.             Return vbNullString
  84.         End If
  85.  
  86.     End Function
  87.  
I included the function GetOneValueNew( because I found that method somewhere on the net, but it was written in VB6. Unfortunately I get 0 back from that.

I tried searching the net but didn't find my answer. I used "VB.NET marshal structure C dll". I included this incase someone may have a better search string.

I even tried writing the code to access the dll in C++. But I get an error in the VB routine that calls it "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." I presume that is also a problem form the unmanaged C dll trying to write to memory allocated in managed C++.

Thanks for looking!
Feb 19 '10 #3
I found out that a pointer to a structure is not the same as a pointer to the memory that the structure occupies. Changed my code to copy the members explicitly.
Expand|Select|Wrap|Line Numbers
  1.         Dim rc As twRC
  2.         Dim pOneValue As IntPtr
  3.         Dim pPosition As Int32 = 0
  4.         Dim strValue As String
  5.         Dim twFix32 As twsFix32
  6.         Dim twOneValue As TW_ONEVALUE
  7.  
  8.  
  9.         rc = DS_Capability(mtwApp, mtwSource, twDG.Control, twDAT.Capability, twMSG.Get, twCapability)
  10.         If rc = twRC.Success Then
  11.  
  12.             twOneValue = New TW_ONEVALUE
  13.             pOneValue = GlobalLock(twCapability.Handle)
  14.             twOneValue.ItemType = CType(Runtime.InteropServices.Marshal.ReadInt16(pOneValue, pPosition), ItemType)
  15.             pPosition += 2
  16.  
  17.             Select Case twOneValue.ItemType
  18.  
  19.                 Case ItemType.Fix32
  20.                     Dim origFrac As Int32
  21.                     twFix32 = New twsFix32
  22.  
  23.                     twOneValue.Item = Marshal.ReadInt16(pOneValue, pPosition)
  24.                     twFix32.Whole = twOneValue.Item
  25.                     pPosition += 2
  26.  
  27.  
  28.                     origFrac = Marshal.ReadInt16(pOneValue, pPosition)
  29.                     If origFrac < 0 Then
  30.                         origFrac += 65536
  31.                     End If
  32.                     pPosition += 2
  33.  
  34.                     'twFix32.Frac = CUShort(origFrac)
  35.                     strValue = (twFix32.Whole + (origFrac / 65536)).ToString
  36.  
  37.                 Case Else
  38.                     MsgBox("Unexpected One Value.  Ignored")
  39.  
  40.             End Select
  41.  
  42.             GlobalUnlock(twCapability.Handle)
  43.  
  44.             Return strValue
  45.  
  46.         End If
Feb 23 '10 #4

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: C. N. Sridhar | last post by:
Hi, I'm writing a wrapper to a win32 dll in C#. I need to call a method in DLL which has a Variant type reference parameter. How to marshal variant type from win32 (unmanaged code) to C#...
3
by: Nikolay Petrov | last post by:
Guys, please help. I am trying to make this work from at least 4 months. I am new to programming and some things are difficult to me, but I really need to make my project work. I can't find...
4
by: Vadym Stetsyak | last post by:
Hi there!!! I'm looking for any resources on the subject. Any help will be appreciated! -- Vadym Stetsyak ICQ 161730125 He, who commands the past - commands the future
5
by: VM | last post by:
What's marshalling? I've had to use it extensively for a project but I don't know what it means. I tried to look for a definition in the Internet but I couldn't find anything that would explain...
1
by: Nadav | last post by:
Hi I am about to write a performance crutial system, I am considering writing this system based on native COM or unmanaged C++ exposed as CLI, Now, I Wonder... does exposing a native code through...
1
by: Chua Wen Ching | last post by:
Hi there, I had some problems converting C -> C#. C codes: unsigned char BYTE; unsigned short puint8; typedef struct {
2
by: mirek | last post by:
Hi, I'm trying to import my old code to the .NET using managed wrappers. I've read "Managed Extensions for C++ Migration Guide" document and was trying to do what it stated in it. For example if...
1
by: Lee Crabtree | last post by:
I have several unmanaged struct types that I've created equivalent managed struct types for. How do I marshal the managed structs into their unmanaged versions and vice versa? Here's a quick...
6
by: Aston Martin | last post by:
Hi All, ********************** My Situation ********************** I am working on project that involves passing a structure to unmanaged code from .Net world (well using C#). Perhaps an example...
0
by: tomwolfstein | last post by:
Hi. I am trying to write a wrapper for the standard VC1 decoder, and I need to resolve a "TypeLoadException" The decoder comes an an executable which I've turned into a .dll. This decoder has about...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.