Home All Groups Group Topic Archive Search About

How to receive an array of doubles using VB from a C DLL

Author
23 Oct 2006 10:45 AM
Neville Lang
Hi all,

Here is a problem I first struck a while back in the Compact Framework. I am
now using the full Framework (v2.0) and wanted to know whether there is
anyway around this issue without building separate shim code in another DLL.

Here is the layout of the external C DLL function:

int thisFunction( [in] double a, [in] int b, [out] double* c)

The double* c argument passes back an array of 6 doubles.

My VB code is like this:

<DllImport("External.DLL")> _
Public Shared Function thisFunction( ByVal a As Double, ByVal b As Integer,
ByRef c As Double() ) As Integer
End Function
...
...
...
Dim iRet As Integer
Dim a As Double
Dim b As Integer
Dim c(5) As Double

a = 36.12
b = 4

iRet = thisFunction( a, b, c )
....
....

At the moment, the call to this function is crashing. What is the best
solution for this type of problem on the full Framework?

Regards,
Neville Lang

Author
23 Oct 2006 2:37 PM
tomb
Is that an old C dll, or a newer C++ dll?  If it's old, it may be using
a 16 bit int, but you are passing it a 32 bit int.  That may be what's
making it crash, rather than the array of doubles.

T

Neville Lang wrote:

Show quoteHide quote
>Hi all,
>
>Here is a problem I first struck a while back in the Compact Framework. I am
>now using the full Framework (v2.0) and wanted to know whether there is
>anyway around this issue without building separate shim code in another DLL.
>
>Here is the layout of the external C DLL function:
>
>int thisFunction( [in] double a, [in] int b, [out] double* c)
>
>The double* c argument passes back an array of 6 doubles.
>
>My VB code is like this:
>
><DllImport("External.DLL")> _
>Public Shared Function thisFunction( ByVal a As Double, ByVal b As Integer,
>ByRef c As Double() ) As Integer
>End Function
>..
>..
>..
>Dim iRet As Integer
>Dim a As Double
>Dim b As Integer
>Dim c(5) As Double
>
>a = 36.12
>b = 4
>
>iRet = thisFunction( a, b, c )
>...
>...
>
>At the moment, the call to this function is crashing. What is the best
>solution for this type of problem on the full Framework?
>
>Regards,
>Neville Lang
>
>

>
Author
23 Oct 2006 2:50 PM
Neville Lang
The DLL is using 32-bit INTs, if that is any help.

Regards,
Neville Lang



Show quoteHide quote
"tomb" <t***@technetcenter.com> wrote in message
news:hv4%g.1798$N4.553@bignews5.bellsouth.net...
> Is that an old C dll, or a newer C++ dll?  If it's old, it may be using a
> 16 bit int, but you are passing it a 32 bit int.  That may be what's
> making it crash, rather than the array of doubles.
>
> T
>
> Neville Lang wrote:
>
>>Hi all,
>>
>>Here is a problem I first struck a while back in the Compact Framework. I
>>am now using the full Framework (v2.0) and wanted to know whether there is
>>anyway around this issue without building separate shim code in another
>>DLL.
>>
>>Here is the layout of the external C DLL function:
>>
>>int thisFunction( [in] double a, [in] int b, [out] double* c)
>>
>>The double* c argument passes back an array of 6 doubles.
>>
>>My VB code is like this:
>>
>><DllImport("External.DLL")> _
>>Public Shared Function thisFunction( ByVal a As Double, ByVal b As
>>Integer, ByRef c As Double() ) As Integer
>>End Function
>>..
>>..
>>..
>>Dim iRet As Integer
>>Dim a As Double
>>Dim b As Integer
>>Dim c(5) As Double
>>
>>a = 36.12
>>b = 4
>>
>>iRet = thisFunction( a, b, c )
>>...
>>...
>>
>>At the moment, the call to this function is crashing. What is the best
>>solution for this type of problem on the full Framework?
>>
>>Regards,
>>Neville Lang
>>
>>
Author
23 Oct 2006 5:21 PM
Mattias Sjögren
Neville,

><DllImport("External.DLL")> _
>Public Shared Function thisFunction( ByVal a As Double, ByVal b As Integer,
>ByRef c As Double() ) As Integer
^^^^^

Should be ByVal


Mattias

--
Mattias Sjögren [C# MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Author
24 Oct 2006 2:46 AM
Neville Lang
Hi Mattias,

I tried your suggestion but it still gives an error.

I am going to revert to my shim code approach as I did in the Compact
Framework, and will report back if I get it working. I had hoped the full
Framework would not have required separate shim code in another DLL to make
receiving 6 doubles work. ( [out] double * construct in the C++ DLL)

Regards,
Neville Lang




Show quoteHide quote
"Mattias Sjögren" <mattias.dont.want.spam@mvps.org> wrote in message
news:%23lqXifs9GHA.3916@TK2MSFTNGP04.phx.gbl...
> Neville,
>
>><DllImport("External.DLL")> _
>>Public Shared Function thisFunction( ByVal a As Double, ByVal b As
>>Integer,
>>ByRef c As Double() ) As Integer
> ^^^^^
>
> Should be ByVal
>
>
> Mattias
>
> --
> Mattias Sjögren [C# MVP]  mattias @ mvps.org
> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
> Please reply only to the newsgroup.
Author
23 Oct 2006 11:55 PM
FishingScout
Neville,

You state that 6 doubles are returned but you are only allocating an
array of 5 to receive those 6 values.

Dim c(6) As Double might do the trick...


Neville Lang wrote:

Show quoteHide quote
> int thisFunction( [in] double a, [in] int b, [out] double* c)
>
> The double* c argument passes back an array of 6 doubles.

> Dim c(5) As Double
>
> a = 36.12
> b = 4
>
> iRet = thisFunction( a, b, c )
Author
24 Oct 2006 2:52 AM
Neville Lang
I tried your suggestion but this did not change anything.

I mainly have a C# background and I understand that in VB .NET, you specify
a value of one less when dimensioning an array as you do in C#. As I
understand it, the figure that is used for the dimension of an array in
VB.NET is the number of the last element - so in my case to get 6 elements
in an array, elements 0 - 5, I dimension an array using "array(5)" in
VB.NET.

As I stated in my reply to Mattias, I will try out my shim code and approach
report back.

Regards,
Neville Lang




Show quoteHide quote
"FishingScout" <fishingsc***@comcast.net> wrote in message
news:1161647708.247066.26410@i42g2000cwa.googlegroups.com...
> Neville,
>
> You state that 6 doubles are returned but you are only allocating an
> array of 5 to receive those 6 values.
>
> Dim c(6) As Double might do the trick...
>
>
> Neville Lang wrote:
>
>> int thisFunction( [in] double a, [in] int b, [out] double* c)
>>
>> The double* c argument passes back an array of 6 doubles.
>
>> Dim c(5) As Double
>>
>> a = 36.12
>> b = 4
>>
>> iRet = thisFunction( a, b, c )
>
Author
24 Oct 2006 3:33 AM
Jay B. Harlow
Neville,
In addition to the other comments, I understand that you need to pass the
array ByVal (as Mattias suggests) plus you need to use the MarshalAs
attribute to indicate an array pointer & the size of the array.

Something like:

    Public Declare Function thisFunction Lib "External.DLL" ( _
            ByVal a As Double, _
            ByVal b As Integer, _
            <Out(), MarshalAs(UnmanagedType.LPArray, SizeConst:=6)> _
                ByVal c As Double() _
        ) As Integer


For details see:

http://msdn2.microsoft.com/en-us/library/z6cfh6e6.aspx


--
Hope this helps
Jay B. Harlow
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


Show quoteHide quote
"Neville Lang" <neville@MAPS_ONnjlsoftware.com> wrote in message
news:eIrB0Bp9GHA.3740@TK2MSFTNGP05.phx.gbl...
> Hi all,
>
> Here is a problem I first struck a while back in the Compact Framework. I
> am now using the full Framework (v2.0) and wanted to know whether there is
> anyway around this issue without building separate shim code in another
> DLL.
>
> Here is the layout of the external C DLL function:
>
> int thisFunction( [in] double a, [in] int b, [out] double* c)
>
> The double* c argument passes back an array of 6 doubles.
>
> My VB code is like this:
>
> <DllImport("External.DLL")> _
> Public Shared Function thisFunction( ByVal a As Double, ByVal b As
> Integer, ByRef c As Double() ) As Integer
> End Function
> ..
> ..
> ..
> Dim iRet As Integer
> Dim a As Double
> Dim b As Integer
> Dim c(5) As Double
>
> a = 36.12
> b = 4
>
> iRet = thisFunction( a, b, c )
> ...
> ...
>
> At the moment, the call to this function is crashing. What is the best
> solution for this type of problem on the full Framework?
>
> Regards,
> Neville Lang
>
Author
24 Oct 2006 8:59 AM
Neville Lang
Jay,

Your feedback on this topic has fixed my problem.

Thank you also for the link to the MSDN information - it was very useful to
understand what is going on here. I must admit that one of my weaknesses in
..NET programming is in using Platform Invoke and the correct construction of
the arguments.

I slightly departed from your code after reading MSDN - I did not use the
Out() attribute - only the MarshalAs() was all that was needed. I also found
that if I only typed in the <MarshalAs(...)> attribute followed by the
argument name, VB.NET automatically put in the "ByVal".

I can now move on...

Regards,
Neville Lang



Show quoteHide quote
"Jay B. Harlow" <Jay_Harlow_***@tsbradley.net> wrote in message
news:AE2B6CC8-6F46-4BDA-91CF-0DF19D2D3F90@microsoft.com...
> Neville,
> In addition to the other comments, I understand that you need to pass the
> array ByVal (as Mattias suggests) plus you need to use the MarshalAs
> attribute to indicate an array pointer & the size of the array.
>
> Something like:
>
>    Public Declare Function thisFunction Lib "External.DLL" ( _
>            ByVal a As Double, _
>            ByVal b As Integer, _
>            <Out(), MarshalAs(UnmanagedType.LPArray, SizeConst:=6)> _
>                ByVal c As Double() _
>        ) As Integer
>
>
> For details see:
>
> http://msdn2.microsoft.com/en-us/library/z6cfh6e6.aspx
>
>
> --
> Hope this helps
> Jay B. Harlow
> .NET Application Architect, Enthusiast, & Evangelist
> T.S. Bradley - http://www.tsbradley.net
>
>
> "Neville Lang" <neville@MAPS_ONnjlsoftware.com> wrote in message
> news:eIrB0Bp9GHA.3740@TK2MSFTNGP05.phx.gbl...
>> Hi all,
>>
>> Here is a problem I first struck a while back in the Compact Framework. I
>> am now using the full Framework (v2.0) and wanted to know whether there
>> is anyway around this issue without building separate shim code in
>> another DLL.
>>
>> Here is the layout of the external C DLL function:
>>
>> int thisFunction( [in] double a, [in] int b, [out] double* c)
>>
>> The double* c argument passes back an array of 6 doubles.
>>
>> My VB code is like this:
>>
>> <DllImport("External.DLL")> _
>> Public Shared Function thisFunction( ByVal a As Double, ByVal b As
>> Integer, ByRef c As Double() ) As Integer
>> End Function
>> ..
>> ..
>> ..
>> Dim iRet As Integer
>> Dim a As Double
>> Dim b As Integer
>> Dim c(5) As Double
>>
>> a = 36.12
>> b = 4
>>
>> iRet = thisFunction( a, b, c )
>> ...
>> ...
>>
>> At the moment, the call to this function is crashing. What is the best
>> solution for this type of problem on the full Framework?
>>
>> Regards,
>> Neville Lang
>>
>
Author
24 Oct 2006 10:48 PM
Jay B. Harlow
Neville,
The <Out> is a hint to the marshaller on what direction the parameter's data
is moving. I included it as your original C prototype included it.

>  I must admit that one of my weaknesses in .NET programming is in using
> Platform Invoke and the correct construction of the arguments.
I find www.pinvoke.net to be invaluable when working with P/Invoke. I also
recommend Adam Nathan's book ".NET and COM - The Complete Interoperability
Guide" from SAMS press if you are doing a lot of P/Invoke.

--
Hope this helps
Jay B. Harlow
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


Show quoteHide quote
"Neville Lang" <neville@MAPS_ONnjlsoftware.com> wrote in message
news:uL9l0q09GHA.3256@TK2MSFTNGP02.phx.gbl...
> Jay,
>
> Your feedback on this topic has fixed my problem.
>
> Thank you also for the link to the MSDN information - it was very useful
> to understand what is going on here. I must admit that one of my
> weaknesses in .NET programming is in using Platform Invoke and the correct
> construction of the arguments.
>
> I slightly departed from your code after reading MSDN - I did not use the
> Out() attribute - only the MarshalAs() was all that was needed. I also
> found that if I only typed in the <MarshalAs(...)> attribute followed by
> the argument name, VB.NET automatically put in the "ByVal".
>
> I can now move on...
>
> Regards,
> Neville Lang
>
>
>
> "Jay B. Harlow" <Jay_Harlow_***@tsbradley.net> wrote in message
> news:AE2B6CC8-6F46-4BDA-91CF-0DF19D2D3F90@microsoft.com...
>> Neville,
>> In addition to the other comments, I understand that you need to pass the
>> array ByVal (as Mattias suggests) plus you need to use the MarshalAs
>> attribute to indicate an array pointer & the size of the array.
>>
>> Something like:
>>
>>    Public Declare Function thisFunction Lib "External.DLL" ( _
>>            ByVal a As Double, _
>>            ByVal b As Integer, _
>>            <Out(), MarshalAs(UnmanagedType.LPArray, SizeConst:=6)> _
>>                ByVal c As Double() _
>>        ) As Integer
>>
>>
>> For details see:
>>
>> http://msdn2.microsoft.com/en-us/library/z6cfh6e6.aspx
>>
>>
>> --
>> Hope this helps
>> Jay B. Harlow
>> .NET Application Architect, Enthusiast, & Evangelist
>> T.S. Bradley - http://www.tsbradley.net
>>
>>
>> "Neville Lang" <neville@MAPS_ONnjlsoftware.com> wrote in message
>> news:eIrB0Bp9GHA.3740@TK2MSFTNGP05.phx.gbl...
>>> Hi all,
>>>
>>> Here is a problem I first struck a while back in the Compact Framework.
>>> I am now using the full Framework (v2.0) and wanted to know whether
>>> there is anyway around this issue without building separate shim code in
>>> another DLL.
>>>
>>> Here is the layout of the external C DLL function:
>>>
>>> int thisFunction( [in] double a, [in] int b, [out] double* c)
>>>
>>> The double* c argument passes back an array of 6 doubles.
>>>
>>> My VB code is like this:
>>>
>>> <DllImport("External.DLL")> _
>>> Public Shared Function thisFunction( ByVal a As Double, ByVal b As
>>> Integer, ByRef c As Double() ) As Integer
>>> End Function
>>> ..
>>> ..
>>> ..
>>> Dim iRet As Integer
>>> Dim a As Double
>>> Dim b As Integer
>>> Dim c(5) As Double
>>>
>>> a = 36.12
>>> b = 4
>>>
>>> iRet = thisFunction( a, b, c )
>>> ...
>>> ...
>>>
>>> At the moment, the call to this function is crashing. What is the best
>>> solution for this type of problem on the full Framework?
>>>
>>> Regards,
>>> Neville Lang
>>>
>>
>
>
Author
24 Oct 2006 11:58 PM
Neville Lang
Jay,

Thank you for the PInvoke.net link and the reference to the book. I have a
number of .NET books but not that one.

I have been working with C# on the Compact Framework for the last few years
so using VB.NET on the full Framework has taken me a bit more time to used
to the VB.NET style. I gave up on VB when it was about version 4 so this
project has given me the opportunity to get back up to speed with the VB
..NET version.

I only occasionally need to do some P/Invoke things and when I do, it is an
area I seem to get caught on. I am quite comfortable in the Compact
Framework (CF) for Pocket PCs and the need to write shim code in a separate
DLL for some calls to make some things work, due to the limited number of
things the Marshal class can do in CF.

Until recently, I have not done much on the full Framework and when this
P/Invoke came up, I just knew that there should have been an easier way to
solve my problem with the larger number of features in marshaling in the
full Framework.

Thanks again.

Regards,
Neville Lang




Show quoteHide quote
"Jay B. Harlow" <Jay_Harlow_***@tsbradley.net> wrote in message
news:16EF48D3-4F56-47FD-B709-5F0A9AB2D15D@microsoft.com...
> Neville,
> The <Out> is a hint to the marshaller on what direction the parameter's
> data is moving. I included it as your original C prototype included it.
>
>>  I must admit that one of my weaknesses in .NET programming is in using
>> Platform Invoke and the correct construction of the arguments.
> I find www.pinvoke.net to be invaluable when working with P/Invoke. I also
> recommend Adam Nathan's book ".NET and COM - The Complete Interoperability
> Guide" from SAMS press if you are doing a lot of P/Invoke.
>
> --
> Hope this helps
> Jay B. Harlow
> .NET Application Architect, Enthusiast, & Evangelist
> T.S. Bradley - http://www.tsbradley.net
>
>
> "Neville Lang" <neville@MAPS_ONnjlsoftware.com> wrote in message
> news:uL9l0q09GHA.3256@TK2MSFTNGP02.phx.gbl...
>> Jay,
>>
>> Your feedback on this topic has fixed my problem.
>>
>> Thank you also for the link to the MSDN information - it was very useful
>> to understand what is going on here. I must admit that one of my
>> weaknesses in .NET programming is in using Platform Invoke and the
>> correct construction of the arguments.
>>
>> I slightly departed from your code after reading MSDN - I did not use the
>> Out() attribute - only the MarshalAs() was all that was needed. I also
>> found that if I only typed in the <MarshalAs(...)> attribute followed by
>> the argument name, VB.NET automatically put in the "ByVal".
>>
>> I can now move on...
>>
>> Regards,
>> Neville Lang
>>
>>
>>
>> "Jay B. Harlow" <Jay_Harlow_***@tsbradley.net> wrote in message
>> news:AE2B6CC8-6F46-4BDA-91CF-0DF19D2D3F90@microsoft.com...
>>> Neville,
>>> In addition to the other comments, I understand that you need to pass
>>> the array ByVal (as Mattias suggests) plus you need to use the MarshalAs
>>> attribute to indicate an array pointer & the size of the array.
>>>
>>> Something like:
>>>
>>>    Public Declare Function thisFunction Lib "External.DLL" ( _
>>>            ByVal a As Double, _
>>>            ByVal b As Integer, _
>>>            <Out(), MarshalAs(UnmanagedType.LPArray, SizeConst:=6)> _
>>>                ByVal c As Double() _
>>>        ) As Integer
>>>
>>>
>>> For details see:
>>>
>>> http://msdn2.microsoft.com/en-us/library/z6cfh6e6.aspx
>>>
>>>
>>> --
>>> Hope this helps
>>> Jay B. Harlow
>>> .NET Application Architect, Enthusiast, & Evangelist
>>> T.S. Bradley - http://www.tsbradley.net
>>>
>>>
>>> "Neville Lang" <neville@MAPS_ONnjlsoftware.com> wrote in message
>>> news:eIrB0Bp9GHA.3740@TK2MSFTNGP05.phx.gbl...
>>>> Hi all,
>>>>
>>>> Here is a problem I first struck a while back in the Compact Framework.
>>>> I am now using the full Framework (v2.0) and wanted to know whether
>>>> there is anyway around this issue without building separate shim code
>>>> in another DLL.
>>>>
>>>> Here is the layout of the external C DLL function:
>>>>
>>>> int thisFunction( [in] double a, [in] int b, [out] double* c)
>>>>
>>>> The double* c argument passes back an array of 6 doubles.
>>>>
>>>> My VB code is like this:
>>>>
>>>> <DllImport("External.DLL")> _
>>>> Public Shared Function thisFunction( ByVal a As Double, ByVal b As
>>>> Integer, ByRef c As Double() ) As Integer
>>>> End Function
>>>> ..
>>>> ..
>>>> ..
>>>> Dim iRet As Integer
>>>> Dim a As Double
>>>> Dim b As Integer
>>>> Dim c(5) As Double
>>>>
>>>> a = 36.12
>>>> b = 4
>>>>
>>>> iRet = thisFunction( a, b, c )
>>>> ...
>>>> ...
>>>>
>>>> At the moment, the call to this function is crashing. What is the best
>>>> solution for this type of problem on the full Framework?
>>>>
>>>> Regards,
>>>> Neville Lang
>>>>
>>>
>>
>>
>