From: Alexey Popkov on
Hello,
There are nice examples in the Documentstion on calling simple functions
defined in the Windows's kernel.dll from Mathematica. For example, it is
easy to call GetTickCount function:

Needs["NETLink`"]
getTickCount = DefineDLLFunction["GetTickCount", "kernel32.dll", "int", {}]

But I have not found any example on calling a function that returns a
structure. I am interested in use GlobalMemoryStatusEx function that
"retrieves information about the system's current usage of both physical and
virtual memory." In C# it is easy to get this information in numerical form:

http://msdn.microsoft.com/en-us/library/aa366589%28VS.85%29.aspx

But how can this be done in Mathematica?



From: Todd Gayley on
At 04:46 AM 3/16/2010, Alexey Popkov wrote:
>Hello,
>There are nice examples in the Documentstion on calling simple functions
>defined in the Windows's kernel.dll from Mathematica. For example, it is
>easy to call GetTickCount function:
>
>Needs["NETLink`"]
>getTickCount == DefineDLLFunction["GetTickCount", "kernel32.dll", "int", {}]
>
>But I have not found any example on calling a function that returns a
>structure. I am interested in use GlobalMemoryStatusEx function that
>"retrieves information about the system's current usage of both physical and
>virtual memory." In C# it is easy to get this information in numerical form:
>
>http://msdn.microsoft.com/en-us/library/aa366589%28VS.85%29.aspx
>
>But how can this be done in Mathematica?


Alexey,

There are several ways to get this memory
information via .NET/Link, including calling the
GlobalMemoryStatusEx function directly from Mathematica.

The first approach I would recommend is to see if
the information is available via a managed API
(that is, in .NET itself), so you can avoid the
hassles of calling a complex DLL function. A
little googling reveals that you can get memory
info from the Windows Management Interface. The
relevant class is Win32_OperatingSystem
(http://msdn.microsoft.com/en-us/library/aa394239(VS.85).aspx).
Translating a little WMI sample code directly into Mathematica gives:

In[52]:== query ==
NETNew["System.Management.ManagementObjectSearcher",
"SELECT * FROM Win32_OperatingSystem"];

In[53]:== resultCollection == query(a)Get[]

Out[53]== =ABNETObject[System.Management.ManagementObjectCollection]=BB

The NETObjectToExpression function conveniently
turns IEnumerable objects like collections into
Mathematica lists. This collection will only have one item in it:

In[54]== mo == First[NETObjectToExpression[resultCollection]]

Out[54]== =ABNETObject[System.Management.ManagementObject]=BB

The URL page above gives the various properties
you can extract from this object, including
TotalVisibleMemorySize, FreePhysicalMemory,
TotalVirtualMemorySize, and
FreeVirtualMemorySize. For example (note that the values are in Kb):

In[55]:== mo["TotalVisibleMemorySize"]

Out[56]== 3143336


If that isn't to your liking, or you just want to
know how to call a DLL function that takes a struct, read on.

One approach that is often overlooked when using
..NET/Link in complex scenarios is to simply write
a little C# or VB code that encapsulates the task
and call it from Mathematica. The spirit of
..NET/Link (and J/Link) is that you can do
virtually anything directly from Mathematica
without dipping into any other languages, but in
some cases it's easier to write some code of your
own, especially since you can often find example
code out there that does almost exactly what you
want. I won't demonstrate this because we can do
what we need here without ever leaving
Mathematica, but it's an important option to keep in mind.


Here's how to call the GlobalMemoryStatusEx
function from Mathematica. The first thing to do
is to find some C# code that demonstrates how to
do it. A great reference for calling Windows DLL
functions from .NET is www.pinvoke.net, and
that's where you can find a C# example for
GlobalMemoryStatusEx
(http://www.pinvoke.net/default.aspx/kernel32.GlobalMemoryStatusEx).
Here's the C# declaration, copied from that site:

[StructLayout(LayoutKind.Sequential, CharSet==CharSet.Auto)]
private class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength == (uint) Marshal.SizeOf(typeof( MEMORYSTATUSEX ));
}
}

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet == CharSet.Auto, SetLastError == true)]
static extern bool GlobalMemoryStatusEx( [In,
Out] MEMORYSTATUSEX lpBuffer);

As you can see, you need to define a custom
struct that the GlobalMemoryStatusEx function
fills in. DefineDLLFunction provides some options
for handling complex function declarations, but
nothing that can handle this level of complexity.
For situations like this, DefineDLLFunction
provides a fallback mode where you can just
supply a string of C# code that represents an
external function declaration in all its complexity:

In[57]:== globalMemoryStatusEx == DefineDLLFunction[
"[StructLayout(LayoutKind.Sequential, CharSet==CharSet.Auto)]
public class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength == (uint)
Marshal.SizeOf(typeof( MEMORYSTATUSEX ));
}
}

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport(\"kernel32.dll\",
CharSet == CharSet.Auto, SetLastError == true)]
public static extern bool
GlobalMemoryStatusEx( [In, Out] MEMORYSTATUSEX lpBuffer);"
];

Out[57]== Function[Null,
If[NETLink`DLL`Private`checkArgCount[GlobalMemoryStatusEx,{##1},1],
Wolfram`NETLink`DynamicDLLNamespace`DLLWrapper1`GlobalMemoryStatusEx[##1],
$Failed], {HoldAll}]

Note that I had to make one change to the
declaration from the website--the MEMORYSTATUSEX
struct was declared private, but it needs to be public.

So far, that was easy--find an example C#
declaration for the function and paste it
directly into Mathematica. There is one
complication, though, which is that we need to
instantiate the MEMORYSTATUSEX structure to pass
it in as the argument to globalMemoryStatusEx.
That struct was defined when the C# compiler was
called by .NET/Link to compile the external
function declaration. But what is its type name?
The answer to that can be found by looking at the
function definition returned by
DefineDLLFunction. You can see that the
GlobalMemoryStatusEx function is in the context
Wolfram`NETLink`DynamicDLLNamespace`DLLWrapper1`,
which corresponds to a .NET class name of
Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1.
That is the class that was automatically created
to hold the GlobalMemoryStatusEx function. You
can also see that this is the created class name
by looking at LoadedNETTypes[]:

In[58]:== LoadedNETTypes[]

Out[58]== {NETType[Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1,1]}

That class is the class in which the
MEMORYSTATUSEX class definition is nested, and if
you know how nested class names in .NET work,
this means that it will have the .NET name of
Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1+MEMORYSTATUSEX.
If you don't know this, you can see the class
name by asking for information about the
definition of the GloalMemoryStatusEx function:

In[59]:==
NETTypeInfo["Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1",
"Methods", "GlobalMemoryStatusEx"]

(prints: )
\[FilledCircle] Methods (matching
string pattern GlobalMemoryStatusEx)

static bool
GlobalMemoryStatusEx(Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1+MEMORYSTATUSEX
lpBuffer)

You can see the type name in the line above.

Now we are ready to call the function. First
create a new instance of the struct:

In[60]:== struct ==
NETNew["Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1+MEMORYSTATUSEX"];

Call the function:

In[61]:== globalMemoryStatusEx[struct];

In[62]:== struct(a)ullTotalPhys

Out[62]== 3218776064



Todd Gayley
Wolfram Research

From: Àëåêñåé Ïîïêîâ on
Todd ,

Many thanks for the detailed response. Both methods are shown by you, very
interesting.

And thanks for sending a separate copy of the message directly to me:
message appeared in the newsgroup is damaged, and part of the code from it
does not work even after the correction of obvious damage.

I have a question on the first method. As I understand, the function
mo["FreePhysicalMemory"]
will return the value corresponding to the time of creation of the first
NETObject ('query'). Thus, it is not suitable for periodic calls on a
regular basis.
How can I get the actual value corresponding to the time of the call? Or how
can I force updating of the values?

Alexey Popkov



----- Original Message -----
From: "Todd Gayley" <tgayley(a)wolfram.com>
To: "Alexey Popkov" <lehin.p(a)gmail.com>; <mathgroup(a)smc.vnet.net>
Sent: Thursday, March 18, 2010 2:22 AM
Subject: Re: Calling kernel.dll from Mathematica


At 04:46 AM 3/16/2010, Alexey Popkov wrote:
>Hello,
>There are nice examples in the Documentstion on calling simple functions
>defined in the Windows's kernel.dll from Mathematica. For example, it is
>easy to call GetTickCount function:
>
>Needs["NETLink`"]
>getTickCount = DefineDLLFunction["GetTickCount", "kernel32.dll", "int", {}]
>
>But I have not found any example on calling a function that returns a
>structure. I am interested in use GlobalMemoryStatusEx function that
>"retrieves information about the system's current usage of both physical
>and
>virtual memory." In C# it is easy to get this information in numerical
>form:
>
>http://msdn.microsoft.com/en-us/library/aa366589%28VS.85%29.aspx
>
>But how can this be done in Mathematica?


Alexey,

There are several ways to get this memory
information via .NET/Link, including calling the
GlobalMemoryStatusEx function directly from Mathematica.

The first approach I would recommend is to see if
the information is available via a managed API
(that is, in .NET itself), so you can avoid the
hassles of calling a complex DLL function. A
little googling reveals that you can get memory
info from the Windows Management Interface. The
relevant class is Win32_OperatingSystem
(http://msdn.microsoft.com/en-us/library/aa394239(VS.85).aspx).
Translating a little WMI sample code directly into Mathematica gives:

In[52]:= query =
NETNew["System.Management.ManagementObjectSearcher",
"SELECT * FROM Win32_OperatingSystem"];

In[53]:= resultCollection = query(a)Get[]

Out[53]= �NETObject[System.Management.ManagementObjectCollection]�

The NETObjectToExpression function conveniently
turns IEnumerable objects like collections into
Mathematica lists. This collection will only have one item in it:

In[54]= mo = First[NETObjectToExpression[resultCollection]]

Out[54]= �NETObject[System.Management.ManagementObject]�

The URL page above gives the various properties
you can extract from this object, including
TotalVisibleMemorySize, FreePhysicalMemory,
TotalVirtualMemorySize, and
FreeVirtualMemorySize. For example (note that the values are in Kb):

In[55]:= mo["TotalVisibleMemorySize"]

Out[56]= 3143336


If that isn't to your liking, or you just want to
know how to call a DLL function that takes a struct, read on.

One approach that is often overlooked when using
..NET/Link in complex scenarios is to simply write
a little C# or VB code that encapsulates the task
and call it from Mathematica. The spirit of
..NET/Link (and J/Link) is that you can do
virtually anything directly from Mathematica
without dipping into any other languages, but in
some cases it's easier to write some code of your
own, especially since you can often find example
code out there that does almost exactly what you
want. I won't demonstrate this because we can do
what we need here without ever leaving
Mathematica, but it's an important option to keep in mind.


Here's how to call the GlobalMemoryStatusEx
function from Mathematica. The first thing to do
is to find some C# code that demonstrates how to
do it. A great reference for calling Windows DLL
functions from .NET is www.pinvoke.net, and
that's where you can find a C# example for
GlobalMemoryStatusEx
(http://www.pinvoke.net/default.aspx/kernel32.GlobalMemoryStatusEx).
Here's the C# declaration, copied from that site:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
private class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint) Marshal.SizeOf(typeof( MEMORYSTATUSEX ));
}
}

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GlobalMemoryStatusEx( [In,
Out] MEMORYSTATUSEX lpBuffer);

As you can see, you need to define a custom
struct that the GlobalMemoryStatusEx function
fills in. DefineDLLFunction provides some options
for handling complex function declarations, but
nothing that can handle this level of complexity.
For situations like this, DefineDLLFunction
provides a fallback mode where you can just
supply a string of C# code that represents an
external function declaration in all its complexity:

In[57]:= globalMemoryStatusEx = DefineDLLFunction[
"[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint)
Marshal.SizeOf(typeof( MEMORYSTATUSEX ));
}
}

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport(\"kernel32.dll\",
CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool
GlobalMemoryStatusEx( [In, Out] MEMORYSTATUSEX lpBuffer);"
];

Out[57]= Function[Null,
If[NETLink`DLL`Private`checkArgCount[GlobalMemoryStatusEx,{##1},1],
Wolfram`NETLink`DynamicDLLNamespace`DLLWrapper1`GlobalMemoryStatusEx[##1],
$Failed], {HoldAll}]

Note that I had to make one change to the
declaration from the website--the MEMORYSTATUSEX
struct was declared private, but it needs to be public.

So far, that was easy--find an example C#
declaration for the function and paste it
directly into Mathematica. There is one
complication, though, which is that we need to
instantiate the MEMORYSTATUSEX structure to pass
it in as the argument to globalMemoryStatusEx.
That struct was defined when the C# compiler was
called by .NET/Link to compile the external
function declaration. But what is its type name?
The answer to that can be found by looking at the
function definition returned by
DefineDLLFunction. You can see that the
GlobalMemoryStatusEx function is in the context
Wolfram`NETLink`DynamicDLLNamespace`DLLWrapper1`,
which corresponds to a .NET class name of
Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1.
That is the class that was automatically created
to hold the GlobalMemoryStatusEx function. You
can also see that this is the created class name
by looking at LoadedNETTypes[]:

In[58]:= LoadedNETTypes[]

Out[58]= {NETType[Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1,1]}

That class is the class in which the
MEMORYSTATUSEX class definition is nested, and if
you know how nested class names in .NET work,
this means that it will have the .NET name of
Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1+MEMORYSTATUSEX.
If you don't know this, you can see the class
name by asking for information about the
definition of the GloalMemoryStatusEx function:

In[59]:=
NETTypeInfo["Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1",
"Methods", "GlobalMemoryStatusEx"]

(prints: )
\[FilledCircle] Methods (matching
string pattern GlobalMemoryStatusEx)

static bool
GlobalMemoryStatusEx(Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1+MEMORYSTATUSEX
lpBuffer)

You can see the type name in the line above.

Now we are ready to call the function. First
create a new instance of the struct:

In[60]:= struct =
NETNew["Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1+MEMORYSTATUSEX"];

Call the function:

In[61]:= globalMemoryStatusEx[struct];

In[62]:= struct(a)ullTotalPhys

Out[62]= 3218776064



Todd Gayley
Wolfram Research



From: Alexey Popkov on
Todd,

Interesting that I seem to have found a way to update the values. For this I
call the method Get[]:

freePhysicalMemoryFromWMI := (mo(a)Get[]; mo["FreePhysicalMemory"]);

I have no idea where this is documented but observations have shown that it
like works correctly.

And it allows me to compare the effectiveness of two methods in terms of CPU
load (I have a dual-core processor) by AbsoluteTiming.
The following code compares the time required to obtain 10000 of actual
values in two ways. Amazingly, the first method is 60 times slower than the
second! It seems that in terms of performance with the frequent call working
with the DLL is preferred.

In[1]:= Needs["NETLink`"]
query=NETNew["System.Management.ManagementObjectSearcher","SELECT * FROM
Win32_OperatingSystem"];
resultCollection=query(a)Get[];
mo=First[NETObjectToExpression[resultCollection]];
freePhysicalMemoryFromWMI:=(mo(a)Get[];mo["FreePhysicalMemory"]);

globalMemoryStatusEx=DefineDLLFunction["[StructLayout(LayoutKind.Sequential,
CharSet=CharSet.Auto)]
public class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint)
Marshal.SizeOf(typeof( MEMORYSTATUSEX ));
}
}

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport(\"kernel32.dll\",
CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool
GlobalMemoryStatusEx( [In, Out] MEMORYSTATUSEX lpBuffer);"];
struct=NETNew["Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1+MEMORYSTATUSEX"];
freePhysicalMemoryFromDLL:=(globalMemoryStatusEx[struct];struct(a)ullAvailPhys
);

Table[freePhysicalMemoryFromWMI,{10000}];//AbsoluteTiming
Table[freePhysicalMemoryFromDLL,{10000}];//AbsoluteTiming

Out[9]= {141.5937500,Null}
Out[10]= {2.3750000,Null}


Alexey Popkov


2010/3/24 Todd Gayley <tgayley(a)wolfram.com>

> At 02:46 AM 3/20/2010, Alexey Popkov wrote:
>
>> Todd ,
>>
>> Many thanks for the detailed response. Both methods are shown by you, very
>> interesting.
>>
>> And thanks for sending a separate copy of the message directly to me:
>> message appeared in the newsgroup is damaged, and part of the code from it
>> does not work even after the correction of obvious damage.
>>
>> I have a question on the first method. As I understand, the function
>> mo["FreePhysicalMemory"]
>> will return the value corresponding to the time of creation of the first
>> NETObject ('query'). Thus, it is not suitable for periodic calls on a
>> regular basis.
>> How can I get the actual value corresponding to the time of the call? Or
>> how
>> can I force updating of the values?
>>
>
>
> Alexey,
>
> Just re-do the entire call when you need the current values. Here is the
> code packaged as a function:
>
> GetMemoryData[] :=
> NETBlock[
> Module[{query, mo},
>
> query = NETNew["System.Management.ManagementObjectSearcher",
> "SELECT * FROM Win32_OperatingSystem"];
> mo = First[NETObjectToExpression[query(a)Get[]]];
> (# -> mo[#])& /@ {"TotalVisibleMemorySize", "FreePhysicalMemory",
> "TotalVirtualMemorySize"}
> ]
> ]
>
>
> In[10]:= GetMemoryData[]
>
> Out[10]= {TotalVisibleMemorySize -> 3143336, FreePhysicalMemory -> 1124652,
> TotalVirtualMemorySize -> 4444440}
>
>
>
> Todd Gayley
> Wolfram Research
>
>


From: Alexey Popkov on
Todd,

Is there a straightforward way to determine which of the loaded NETTypes
corresponds to a function returned by DefineDLLFunction? Or the only way is
to use Definition[]?

Alexey Popkov


----- Original Message -----
From: "Todd Gayley" <tgayley(a)wolfram.com>
To: "Alexey Popkov" <lehin.p(a)gmail.com>; <mathgroup(a)smc.vnet.net>
Sent: Thursday, March 18, 2010 2:22 AM
Subject: Re: Calling kernel.dll from Mathematica
<...>

You can see that the
GlobalMemoryStatusEx function is in the context
Wolfram`NETLink`DynamicDLLNamespace`DLLWrapper1`,
which corresponds to a .NET class name of
Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1.
That is the class that was automatically created
to hold the GlobalMemoryStatusEx function. You
can also see that this is the created class name
by looking at LoadedNETTypes[]:

In[58]:= LoadedNETTypes[]

Out[58]= {NETType[Wolfram.NETLink.DynamicDLLNamespace.DLLWrapper1,1]}
<...>

Todd Gayley
Wolfram Research