<html>
<body>
I have succeeded in calling the downloaded CoiniMP.Dll through a<br>
wrapper DLL in Visual Studio C++.<br><br>
Visual Studio, Visual Basic and related languages use MicroSoft's<br>
managed code options and a common language runtime.&nbsp; <br><br>
For managed code:<br>
(1) arrays are handled differently, and references to elements are<br>
checked for lengths. This means passing the array itself as a <br>
parameter is not by pointing to the first element, but to a <br>
structure containing the data.<br>
(2) Strings are arrays, but the characters are all Unicode, which<br>
is two bytes.<br>
(3) Pointers as such don't exist. This solves a lot of security and<br>
integrity problems; you can't just mess up a random bit of system<br>
memory or somebody else's program.<br>
(4) Instead, there are references. These are sort of like pointers<br>
to safe data structures.<br>
(5) Related to this, you can't have &quot;variants,&quot; treated the
same<br>
physical memory as different memory areas. The COINMP.DLL<br>
routines depends on a C-language pointer to void (void*) type,<br>
to hold C++ data structures.<br>
(6) All VB memory is &quot;managed&quot; memory; it has to keep
track<br>
of who is using each piece in order to know when to delete it.<br>
Garbage collection is good, and prevents a whole set of problems,<br>
but it is absolutely incompatible with C++ memory allocations.<br><br>
The C++ language itself has&nbsp; features that present problems:<br>
(1) Standard C/C++ strings are arrays of char, with null <br>
terminations. Char in C is a byte = 8 bits. The null terminator<br>
adds one byte to each string.<br>
(2) There are no multiple-level arrays as such. Instead, data <br>
with more than one level is treated as an array of pointers<br>
at the top level. <br><br>
Putting this together, it appears that char** structures needed for<br>
rowNames and colNames parameters are impossible to create<br>
in Visual Basic.<br><br>
However, MS Visual Studio also includes a version of Visual C++<br>
that allows you to write a wrapper as an interface between<br>
managed and unmanaged code.<br><br>
Even in managed code, arrays of basic types like Byte, Char,<br>
Integer and Double have elements stored in consecutive storage.<br>
And you can specify calling by reference as a keyword ByRef.<br>
If you specify an array as a ByRef to the first element, it is<br>
equivalent to a pointer to the array storage.<br><br>
Thus, I can specify a VB array like this:<br>
<tt>&nbsp;Dim rhsValues() As Double = {20.0, 30.0, 0.0}<br><br>
</tt>I declare the calling routine with a set of parameters like
this;<br>
...<br>
<tt>&nbsp;&nbsp; ByRef RHSValues As Double, _<br>
</tt><font face="Arial, Helvetica">...<br><br>
Then I call the routine with a reference to the first element of
each<br>
array, like this:<br>
...<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rhsValues(0), _<br>
...<br>
And, as a result, the C++ routines can see the physical storage <br>
allocated in VB as a series of adjacent elements at an address.<br><br>
The HPROB data structure created and returned by the COINMP<br>
calls are also antithetical to managed code. The only way I found <br>
to get around this was to make the Visual C++ wrapper, and store<br>
the pointer as a global variable. (It might work to create a new <br>
object type with HPROB member for each instance.)<br><br>
</font><tt>static void * theHProb; <br><br>
</tt>which is saved by a wrapping routine like this:<br><br>
<tt><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab>
WSOLVAPI void&nbsp; WCoinCreateProblem(char * ProblemName)
{<x-tab>&nbsp;</x-tab><br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab><x-tab>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab>theHProb =
CoinCreateProblem (ProblemName);<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab><x-tab>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab>return;<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab>} // end
wrapCoinMP<br><br>
</tt>and used by the other wrapping calls like this:<br><br>
<tt><x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab>
WSOLVAPI int WCoinOptimizeProblem(int Method){<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab><x-tab>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab>return
CoinOptimizeProblem(theHProb,Method);<br>
<x-tab>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</x-tab>} //
WCoinOptimizeProblem<br><br>
</tt>so that the offending data structure is never stored the managed
code <br>
routine. <br><br>
In Visual Basic, I use the DLLImport attribute. I was not able to call
any other<br>
way than this. Here is a sample declaration of a call to one of my
wrapper<br>
functions:<br><br>
<tt>&nbsp;&nbsp;&nbsp; &lt;DllImport(&quot;WrapCoinMP.dll&quot;)&gt;
_<br>
&nbsp;&nbsp;&nbsp; Function WCoinOptimizeProblem(ByVal Method As Integer)
_<br>
&nbsp;&nbsp;&nbsp; As Integer<br><br>
&nbsp;&nbsp;&nbsp; End Function<br><br>
</tt>My wrapper for CoinLoadProblem includes a routine for unpacking byte
<br>
arrays for rowNames and ColNames.<br><br>
VB caller: converts VB strings to Byte arrays, and passes the first
element<br>
VC++ wrapper: converts the passed Byte arrays (char arrays) to a
series<br>
&nbsp;&nbsp;&nbsp;&nbsp; of separate C strings with null terminators, and
an array of C pointers to<br>
&nbsp;&nbsp;&nbsp;&nbsp; the strings.<br><br>
Then the wrapper routine calls the CoinMP routine DLL.<br><br>
This message provides clues about how to do all this. If I get the code
cleaned<br>
up OK, I might send the whole code for the test caller and the wrapper
functions.<br><br>
LAT</body>
</html>