473,756 Members | 9,433 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Marshal Structure containing arrays to function in DLL

Hi,
I'm upgrading a VB6 app to VB.net and I'm having a problem with a call to a
function provided in a DLL.

The function takes the address of a structure which it will fill in with
values.

I get an error:
----------------
An unhandled exception of type 'System.NullRef erenceException ' occured in
Project1.exe

Additional Information: Object reference not set to an instance of an object.
----------------

Based on the UPGRADE_TODOs etc that the upgrade wizard put in my code, I
suspect the problem is with marshaling the VB struct to the unmanaged
function.

Below is a (rather long) description of how the VB looked in VB6, what the
wizard turned it into, the C signature of the function, and some of the
things I've tried.

I would be very grateful for suggestions on how to pass the structure
correctly or where to find a good explanation of the rules. Thanks!
in VB6, it was like this
' the structure that the function takes as a parameter
Public Type NifInterfaceInf o ' Interface Infor structure
interfaceName(N IF_NAME_LEN) As Byte
DeviceID(DEV_ID _SIZE) As Byte
End Type

' the declaration of the function that takes the NifInterfaceInf o struct
Declare Function nifGetInterface List Lib "nifbstd" (ByVal session As Long,
ByRef numIntf As Integer, ByRef info As NifInterfaceInf o) As Long

' an example of a subroutine which invokes the function
Private Sub OpenSess()
' Open a fieldbus Session
Ret (nifOpenSession (vbNull, SessionDesc))

' Pass the max interface number to function "nifGetInterfac eList"
NoOfInterfaces = MAX_INTERFACES

' Get all the interface information
Ret (nifGetInterfac eList(SessionDe sc, NoOfInterfaces, InterfaceInfo(0 )))

For i = 0 To NoOfInterfaces - 1
' The interfaceName and DeviceID are array of byte, need to be
converted by function "getString"
ListInterface.A ddItem getString(Inter faceInfo(i).int erfaceName)
Next

End Sub

The upgrade wizard did this:
Public Structure NifInterfaceInf o ' Interface Infor structure
<VBFixedArray(N IF_NAME_LEN)> Dim interfaceName() As Byte
<VBFixedArray(D EV_ID_SIZE)> Dim DeviceID() As Byte

'UPGRADE_TODO: "Initialize " must be called to initialize instances
of this structure. Click for more:
'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?ke yword="vbup1026 "'
Public Sub Initialize()
ReDim interfaceName(N IF_NAME_LEN)
ReDim DeviceID(DEV_ID _SIZE)
End Sub
End Structure

'UPGRADE_WARNIN G: Structure NifInterfaceInf o may require marshalling
attributes to be passed as an argument in this Declare statement. Click for
more: 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?ke yword="vbup1050 "'
Declare Function nifGetInterface List Lib "nifbstd" (ByVal session As
Integer, ByRef numIntf As Short, ByRef info As NifInterfaceInf o) As Integer
Private Sub OpenSess()
' Open a fieldbus Session
Ret((nifOpenSes sion(VariantTyp e.Null, SessionDesc)))

' Pass the max interface number to function "nifGetInterfac eList"
NoOfInterfaces = MAX_INTERFACES

' Get all the interface information
Ret((nifGetInte rfaceList(Sessi onDesc, NoOfInterfaces,
InterfaceInfo(0 ))))

For i = 0 To NoOfInterfaces - 1
' The interfaceName and DeviceID are array of byte, need to be
converted by function "getString"
ListInterface.I tems.Add(getStr ing(InterfaceIn fo(i).interface Name))
Next

End Sub

--------------

The underlying C declarations are like this:
typedef struct nifInterfaceInf o_t {
char interfaceName[NIF_NAME_LEN];
char deviceID[DEV_ID_SIZE + 1];
} nifInterfaceInf o_t;

extern nifError_t nifGetInterface List(nifDesc_t ud, int16 *numInterfaces,
nifInterfaceInf o_t *info);
--------------

As suggested by the UPGRADE_TODO vbup1026, I added a call to Initialize()
like this:
Private Sub OpenSess()
' Open a fieldbus Session
Ret((nifOpenSes sion(VariantTyp e.Null, SessionDesc)))

' Pass the max interface number to function "nifGetInterfac eList"
NoOfInterfaces = MAX_INTERFACES

InterfaceInfo.I nitialize()
For i = InterfaceInfo.G etLowerBound(0) To
InterfaceInfo.G etUpperBound(0)
InterfaceInfo(i ).Initialize()
Next

' Get all the interface information
Ret((nifGetInte rfaceList(Sessi onDesc, NoOfInterfaces,
InterfaceInfo(0 ))))

For i = 0 To NoOfInterfaces - 1
' The interfaceName and DeviceID are array of byte, need to be
converted by function "getString"
ListInterface.I tems.Add(getStr ing(InterfaceIn fo(i).interface Name))
Next

End Sub

I examined InterfaceInfo in the debugger, and it looks ok following the
call(s) to Initialize().

The call to nifGetInterface List fails with an error
----------------
An unhandled exception of type 'System.NullRef erenceException ' occured in
Project1.exe

Additional Information: Object reference not set to an instance of an object.
----------------

if I add this
<StructLayout ( LayoutKind.Sequ ential, CharSet:=CharSe t.ANSI)>

to the structure declaration, I get the same error.
If I add MarshalAs attributes (as suggested by UPGRADE_WARNING : Structure
NifInterfaceInf o may require marshalling attributes to be passed as an
argument in this Declare statement. Click for more:
'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?ke yword="vbup1050 "):

<StructLayout(L ayoutKind.Seque ntial, CharSet:=CharSe t.Ansi)> _
Public Structure NifInterfaceInf o ' Interface Infor structure
<VBFixedArray(N IF_NAME_LEN), MarshalAs(Unman agedType.ByValT Str,
SizeConst:=NIF_ NAME_LEN)> Dim interfaceName() As Byte
<VBFixedArray(D EV_ID_SIZE), MarshalAs(Unman agedType.ByValT Str,
SizeConst:=DEV_ ID_SIZE)> Dim DeviceID() As Byte

'UPGRADE_TODO: "Initialize " must be called to initialize instances
of this structure. Click for more:
'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?ke yword="vbup1026 "'
Public Sub Initialize()
ReDim interfaceName(N IF_NAME_LEN)
ReDim DeviceID(DEV_ID _SIZE)
End Sub
End Structure

then I get error:
----------------
An unhandled exception of type 'System.TypeLoa dException' occured in
Project1.exe

Additional Information: Can not marshal field interfaceName of type
NifInterfaceInf o: This type can not be marshaled as a structure field
----------------


Anyone have suggestions for the right way to pass a VB.net struct containing
fixed length arrays to a DLL?
Jun 12 '06
10 4993

David Fort (donotspam) wrote:
Here is the magic syntax:

<StructLayout(L ayoutKind.Seque ntial)> _
Public Structure NifInterfaceInf o
<MarshalAs(Unma nagedType.ByVal Array, SizeConst:=NIF_ NAME_LEN + 1)> _
Public interfaceName As Byte()
<MarshalAs(Unma nagedType.ByVal Array, SizeConst:=DEV_ ID_SIZE + 1)> _
Public DeviceID As Byte()
Public Sub Initialize()
ReDim interfaceName(N IF_NAME_LEN)
ReDim DeviceID(DEV_ID _SIZE)
End Sub
End Structure
Declare Function nifGetInterface List Lib "nifbstd" (ByVal session As
Integer, ByRef numIntf As Short, <Out()> ByVal info As NifInterfaceInf o()) As
Integer

Public InterfaceInfo(M AX_INTERFACES) As NifInterfaceInf o
and call it like this:
nifGetInterface List(SessionDes c, NoOfInterfaces, InterfaceInfo)
So, the only change from Tom's last suggestion was the addition of <Out()>
in the function declaration on the third argument.


David - I'm glad you got this figured out. I've been busy the last
couple of days, and wasn't able to respond.

--
Tom Shelton [MVP]

Jun 16 '06 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1505
by: Ivan | last post by:
Hi All, I have a problem with marshaling complex structures (containing numbers, strings, arrays of another structures) to native C function in dll. I have already posted same question to .compactframework thread, but nobody helped. main problem is that I have tried all the workarounds I have found in the Inet but nothing worked... I tried passing IntPtr, Byte Arrays, Serialisation, even used OpenNETCF, but
1
7228
by: Eric Hendriks | last post by:
// In an unmanaged DLL the following function must be called: // int VFGeneralize(const BYTE * const * features); // "features" parameter is supposed to be an array of byte arrays. // function is Marshaled as follows: static extern int VFGeneralize(byte features); In C# I have the following: // Allocate memory to store "Count" references to byte arrays
3
3288
by: kevin | last post by:
Hi I have a C struct that is of the following typedef struct{ DWORD num_conversions; ... short *sample_values; ....
0
1641
by: Ivan | last post by:
Hi All, I have a problem with marshaling complex structures (containing numbers, strings, arrays of another structures) to native C function in dll. I have already posted same question to .compactframework thread, but nobody helped. main problem is that I have tried all the workarounds I have found in the Inet but nothing worked... I tried passing IntPtr, Byte Arrays, Serialisation, even used OpenNETCF, but
1
6314
by: nicewenyan | last post by:
I want to pass a managed c# byte (8 bit) array into a unmanaged c++ function: extern "C" void AddData(unsigned int* data); I use P/Invoke on managed side to do the marshaling as following: public static extern int AddData(IntPtr data);
4
4728
by: cleanrabbit | last post by:
Hello! I hate having to do this, because im almost certain there is someone in the world that has come across this problem and i just havent found their solution yet, so i do appologise if this has already been covered. I have been trying to learn c# as fast as possible in the last month and in doing so i have been re-visiting old C/C++ problems and trying to overcome them in C#. What i have is a very complex serise of structures. Id...
0
2104
by: RobbieJosefson | last post by:
I want to marshal a structure containing a variable length array which will be populated within a C++ dll. the structure is the following Public Structure myStructure{ Public int size; Public myInsideStructure inside; }; The myInsideStructure just contains a string. The problem is the size of the myInsideStructure wont be known until runtime and the size variable will have the number of posts in the myInsideStructure structure...
0
2134
by: Charming12 | last post by:
Hi All, I have a strange problem and due to my inefficiency with IntPtr i am unable to figure it out. I have an structure something like: public struct Detail { public int age; public Detail(int _age)
3
3313
by: Charming12 | last post by:
Hi All, This is a problem which is eating my head from several days. I have a structure which contains an array of elements as public byte pinNumbers;
0
9117
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9679
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9676
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7078
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6390
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5156
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3651
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3141
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2508
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.