[C#] PtrToStructure problem

  • Thread starter Mateusz [PEYN] Adamus
  • Start date
M

Mateusz [PEYN] Adamus

Hi

First of all please let me know if there is some other, more suitable
group for this news - TIA :)


Now, my problem. I'm writing an C# application in which I'm using some
functions from DLL. This dll has been written in C.

One of these functions returns as a result a structure, in example:

[StructLayout(LayoutKind.Sequential, Pack=2)]
internal class myStruct
{
public short someNumber;
public IntPtr handle;
}


OK. Now in this handle there is a pointer to a structure with actuall
results.

[StructLayout(LayoutKind.Sequential, Pack=2)]
internal class myStruct2
{
public uint count; //number of values return from function
public uint current; //current value
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)]
public short[] items; //array of results
}

OK. Hope you're still with me :D

Now, as you can see there is another array in myStruct2. This array
contains result which I want to get :D

In this function description I have something like this:
<description>
The items value is simply a placeholder for the start of the actual
array, which must be allocated when the container is allocated.
</description>


In my application I have something like this:

<code>
[DllImport("some.dll", EntryPoint="#1")]
private static extern short getValues([In, Out] myStruct cap);

myStruct ms = new myStruct();
getValues(ms);

myStruct2 ms2 = new myStruct2();
ms2 = (myStruct2)Marshal.PtrToStructure(ms.handle, typeof(myStruct2));
</code>

In return I get some really strange values in ms2.count and ms2.current.
Not mentioning that I can't get the values from the items :-(

What am I doing wrong? Meybe there is something missing?

best regards
Mateusz [PEYN] Adamus
 
M

Martin Dechev

Hi,

You can try something like this (at least to see if the data in the array
makes more sense):

myStruct s1 = new myStruct();
getValues(s1);
int length = Marshal.ReadInt32(s1.handle);
short[] values = new short[length];
Marshal.Copy((IntPtr)(s1.handle.ToInt32() + 2 * sizeof(int)), values, 0,
length);

Don't forget to free the memory that s1.handle is pointing to.

Hope this helps,
Martin Dechev
ASP.NET MVP
 
M

Mateusz [PEYN] Adamus

Martin Dechev napisa³(a):
Hi,
[cut]

Don't forget to free the memory that s1.handle is pointing to.


Hi

Thank for the reply.

I don't know why but I can't make it work. Meybe I just simplified it
too much. So I'll give you full example with real data - meybe than
you'll figure out what is wrong.

OK. I'm doing a Twain library in C#. I want to get what type of units is
set on the scanner. In C I have these structures:

<c>
typedef struct {
TW_UINT16 Cap; /* ID of capability to get or set */
TW_UINT16 ConType; /* TWON_ONEVALUE, TWON_RANGE, */
/* TWON_ENUMERATION or TWON_ARRAY */
TW_HANDLE hContainer; /* Handle to container of type */
/* ConType */
} TW_CAPABILITY, FAR *pTW_CAPABILITY;
</c>

I've translated into:
<c#>
public short Cap;
public short ConType;
public IntPtr Handle;
</c#>


Handle can be of many types, one of them is TW_ENYMERATION

<c>
typedef struct {
TW_UINT16 ItemType;
TW_UINT32 NumItems;
TW_UINT32 CurrentIndex;
TW_UINT32 DefaultIndex;
TW_UINT8 ItemList[1];
} TW_ENUMERATION, FAR * pTW_ENUMERATION;

ItemList[1] = The enumerated list: one value resides within each array
element. Space for the list is not allocated inside this structure. The
ItemList value is simply a placeholder for the start of the actual
array, which must be allocated when the container is allocated. Remember
to typecast the allocation to ItemType, as well as references to the
elements of the array.
</c>

<c#>
public ushort ItemType;
public uint NumItems;
public uint CurrentIndex;
public uint DefaultIndex;
public short[] ItemList;
</c#>

OK. That's it. I also have an example in the Twain's documentation on
how to get values from the scanner but I just can't figure out way on
how to translateg to the C#. Its probably very easy but I'm noobie in C#
so its darn hard for me :-(

example:
<c>
pTW_ENUMERATION pvalEnum;
TW_UINT16 valueU16;
TW_UINT16 index;
pvalEnum = (pTW_ENUMERATION)GlobalLock(twCapability.hContainer);
NumItems = pvalEnum->NumItems;
CurrentIndex = pvalEnum->CurrentIndex;
DefaultIndex = pvalEnum->DefaultIndex;
for (index = 0; index < pvalEnum->NumItems; index++)
{
if (pvalEnum->ItemType == TWTY_UINT16)
{
valueU16 = ((TW_UINT16)(pvalEnum->ItemList[index*2]));
//Store Item Value
}
}
GlobalUnlock(twCapability.hContainer);
</c>


TIA for all replies

best regards
Mateusz [PEYN] Adamus
 
M

Mateusz [PEYN] Adamus

Mateusz [PEYN] Adamus napisa³(a):
Hi

Thank for the reply.

I don't know why but I can't make it work. Meybe I just simplified it
too much. So I'll give you full example with real data - meybe than
you'll figure out what is wrong.

OK. I'm doing a Twain library in C#. I want to get what type of units is
set on the scanner. In C I have these structures:
[cut]

TIA for all replies

best regards
Mateusz [PEYN] Adamus

Heh. It seems that it wasn't so hard after all. I don't know what was
happening with me on Firday - probably the weekend thing :D

Anyways I just figured out way to get all data. :)


best regards
Mateusz [PEYN] Adamus
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top