MathGroup Archive 2004

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Re: Re: Net/Link: Problem with DLL (2)

  • To: mathgroup at smc.vnet.net
  • Subject: [mg49055] Re: [mg48918] Re: [mg48888] Re: Net/Link: Problem with DLL (2)
  • From: Todd Gayley <tgayley at wolfram.com>
  • Date: Tue, 29 Jun 2004 04:50:46 -0400 (EDT)
  • References: <200406220931.FAA10242@smc.vnet.net>
  • Sender: owner-wri-mathgroup at wolfram.com

At 01:51 AM 6/23/2004, Peter S Aptaker wrote:
>After more reading and experimenting have now got something 'working' but
>have some more questions:
>
>My Fortran DLLs are imported to Excel via VBA (see below).   I have tried to
>use the 'self documenting VB format for clarity but have
>only beem able to preserve it precisely for Double scalars as:
>
>(1) Comment: To get Int32 I have replaced Long by long;  I recall  .Net has
>longer
>default Integers.


Peter,

To get Int32 you can use Int32, Integer or long (the latter being a Win32 C 
long).


>(2) Comment: the OUT array "second from last arg" seems to only be
>possible with Double[].


Yes, you need to declare "out" arrays as array types. This is also the case 
in C# and Visual Basic .NET. Your example VB declaration below uses 'ByRef 
res As Double' for this argument, but that won't work for VB. ByRef As 
Double will cause VB to pass the address of a double to the DLL, which is 
fine if the DLL function is going to write a single value into this 
address. But if the function expects to fill an array of values starting 
from that address it won't work. If the function writes a lot of data it 
might crash, and even if it doesn't you will just get back the first value 
of the array in the double slot.

In VB .NET you would use 'ByVal res() As Double' for that argument, and in 
C# you would use 'double[]'. Either of those type specifications will work 
fine in DefineDLLFunction. Mathematica's DefineDLLFunction uses the same 
type specifications as you would need to use in Visual Basic .NET or C# for 
all arguments.


>(3) Question: .. How can I make this a two dmensional array OUT. As you will
>see I currently use a 1-D array and
>Partition[]?


Partitioning after the fact is the right way. To the DLL function, a 
multidimensional array is just a flat block of memory, so treat it that way 
on the .NET side and let Mathematica restore the partitioning later.


>(4) Comment: the OUT "last arg" seems best as,  out int ;  as the  manual
>suggests.
>
>I guess this hybrid style is a mess but it was hard getting it working!


As you say, the manual recommends using the C#-style "out int" declaration 
for arguments that are "the address of a single integer". You can use 
VB-style "ByRef x As Integer" if you like, but if you pass a ByRef 
parameter, .NET/Link doesn't know that the function isn't expecting a value 
of the right type going in, so you need to assign the symbol a throwaway 
value of the correct type to make the call:

     (* In C, foo is declared as void foo(int* x) and it writes an integer 
into x. *)

     DefineDLLFunction["foo", "somelib.dll", "Void", {"ByRef x As Integer"}]

     x = 42;  (* Must assign garbage int value because ByRef was used in 
the declaration *)
     foo[x]

     (* x has a new integer value now *)

If you declare the argument as "out int" instead, then .NET/Link doesn't 
care what value, if any, x has going into the function. VB .NET has no 
"out-only" notation, so it's often best to switch to C#-style notation for 
these types of arguments. In all other cases you can use pure VB.NET-style 
syntax if you prefer it.


Todd Gayley
Wolfram Research



>Note that a real DLL would be needed to actually test this
>
>Mathematica
>=========
>In[407]:=
>Clear[psaInductanceDLL, psaInductancedll];
>psaInductancedll =
>DefineDLLFunction["psaMagIndMr2", "maths0000.dll",
>"Void", {"ByVal m As long", "ByVal rp As Double", "Double[]",
>"ByVal np As long", "ByVal rq As Double", "Double[]",
>"ByVal nq As long", "ByVal gpp As long", "ByVal gpq As long",
>"double[]", "out int"}]
>
>psaInductanceDLL[m_,rp_, zpl_List, rq_, zql_List, opt___Rule] :=
>Module[{ores},
>ores = MakeNETObject[Table[0.0, {np*nq}]];
>psaInductancedll[m, rp, zpl, np, rq, zql, nq, 4, 3, ores, status];
>res = Partition[NETObjectToExpression[ores] , {np}]
>]
>psaInductanceDLL is fast.
>
>My VBA (i.e. VB6) delaration is:
>=======================
>Declare Sub psaMagIndMr3 Lib "maths0000.dll" ( _
>ByVal m As Long, _
>ByVal rp As Double, ByRef zpl As Double, ByVal np As Long, _
>ByVal rq As Double, ByRef zql As Double, ByVal nq As Long, _
>ByVal gpp As Long, ByVal gpq As Long, _
>ByRef res As Double, ByRef status As Long)
>
>
>Thanks
>
>Peter Aptaker
>
>----- Original Message -----
>From: "psa" <psa at laplacian.co.uk>
To: mathgroup at smc.vnet.net
>To: mathgroup at smc.vnet.net
>Subject: [mg49055] [mg48918] [mg48888] Re: Net/Link: Problem with DLL (2)
>
>etc etc


  • Prev by Date: Re: Simplifying with assumptions
  • Next by Date: Palettes on a Mac Help
  • Previous by thread: Re: Re: Net/Link: Problem with DLL (2)
  • Next by thread: Finding Recursive Pattern