-
dll file
I need to make dll file for computing user defined function in Lindo Lingo. I need to implement two new functions, but I can make only one myuser.dll file for use in Lingo.
But, talking with people from Lindo, it is possible to make two argument myuser.dll function, with first first argument as a "branching" variable. for example, For example,
@USER( 1, 2.4)
might compute the sin of 2.4, while
@USER( 2, 2.4)
would compute the cosine of 2.4. The first argument of 1 implies return the sin, while a first argument of 2 implies return the cosine.
My question is how to do that, because I am new to Vc++.
Thanks in advance,
Aleksandar
-
So what do you have a question about? Do you know how to write a function? Do you know how to make a .dll file? Is there an actual reason why you have to only have one name (a .dll can have many many many many many many functions inside it)?
-
I know how to make .dll file, and my question is how to write a function. There is actual reason to have only one name, because of Lingo language. When Lingo starts up, it searches for .dll file named MYUSER.dll. If he finds him, it loads .dll into memory and calls the exported MYUSER routine every time when it needed.
-
This is an example from lingo manual, but only for one function. I need it for two.
User Defined Functions
The @USER function allows the use of custom functions of your own design in LINGO. In Windows
versions of LINGO, you provide a Dynamic Link Library (DLL) that contains your @USER function.
Most programming languages that support Windows should allow you to build a DLL. For platforms
other than Windows, you provide LINGO with a compiled C or FORTRAN subroutine containing
your @USER function.
From the perspective of a LINGO modeler, an @USER function is a function that can take any number
of arguments, but must take at least one. It returns a result calculated by the user-written routine.
From the perspective of the programmer writing the custom function, an @USER function takes only
two input arguments and returns a single result. The two input arguments consist of:
1. an integer specifying the number of arguments encountered in the @USER
reference in the LINGO model, and
2. a vector containing the values of the arguments in the order in which they
were encountered in the @USER reference in double precision format (i.e.,
an 8 byte floating point format).
In other words, although to the LINGO modeler an @USER function can appear to take any number of
arguments, to the programmer implementing the @USER function, only two input arguments are
passed.
It is possible to use multiple functions with @USER by writing and compiling each function as a
separate subroutine and taking an argument to @USER as the index number of the subroutine that you
want to branch to.
Installing @USER Under Windows
When LINGO for Windows starts up, it searches for the DLL file called MYUSER.DLL. LINGO
searches for this file in your startup directory. The startup directory is the directory where you
installed the LINGO program. If LINGO finds MYUSER.DLL, it loads the DLL into memory and calls
the exported MYUSER routine every time a model references an @USER function.
On platforms other than Windows, you must link a compiled FORTRAN or C subroutine with the
LINGO libraries in order to provide a customized @USER function. Refer to the README file for
your version of LINGO for technical information on how to link your custom routines with LINGO.
In the following section, we illustrate the details of building such a DLL using Microsoft Visual C++.
Visual C++ Example
In this section, we will use Microsoft Visual C/C++ to create a 32-bit DLL that contains an @USER
function to perform the square root function. This is very easy to do if we make use of the AppWizard
in Visual C++ to build the base code for the DLL. Or, you will find the code for this example in the
USER\VC++ subdirectory off of your main LINGO directory. To build the base code, start the Visual
C++ Developer Studio and do the following:
1. Issue the File|New command.
2. You should now see a New dialog box. Select the Project Workspace
options and then click OK.
3. You will now see a New Project Workspace dialog box. Give the project the
name sqroot. In the Type box, select the MFC AppWizard (dll) option. Click
on the Create button.
4. A new MFC AppWizard dialog box should appear. Simply click on the
Finish button.
5. You should now see a New Project Information box containing a summary
of the options selected for your project that resembles:
Click the OK button to finish creating the base code for our DLL.
Now, edit the SQROOT.CPP file and add the modifications listed below in bold:
[sqroot.cpp : Defines the initialization
Quote:
Code:
// routines for the DLL.
//#include "stdafx.h"
#include "sqroot.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////
// CSqrootApp
BEGIN_MESSAGE_MAP(CSqrootApp, CWinApp)
//{{AFX_MSG_MAP(CSqrootApp)
//NOTE-the ClassWizard will add and
// remove mapping macros here.
// DO NOT EDIT what you see in these
// blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CSqrootApp::CSqrootApp()
{
// The constructor
// Remove next line for a "quiet" version
// of MyUser.DLL
AfxMessageBox("@USER DLL installed");
}
CSqrootApp theApp;
#include <math.h>
extern "C" __declspec(dllexport)
void MyUser(int* pnNumberOfArgs,
double* pdArgs, double* dResult)
{
// This is an @USER routine callable by LINGO. In
// this particular case we simply take the
// square root of the first argument.
*dResult = sqrt(*pdArgs);
}
[/CODE]You should now be able to build the DLL. When Visual C++ completes the build, copy the
SQROOT.DLL file to LINGO’s startup directory (the one where LINGO13.EXE or LINGO64-13.EXE
is located) and rename SQROOT.DLL to be MYUSER.DLL. Now, start LINGO and you should see the
following dialog box confirming the DLL was successfully loaded:
Input a small model to compute the square root of 9 and solve it to get the following results:
If
-
So your other tool only looks for one function, despite however many there are. That's fine. I have no idea how you could have gotten to "can make a DLL" without going through "writing a function", so ... well done for that, I guess. Did you read the example you posted? There's an example of what the function must look like, in terms of prototypes; and they even tell you what each argument is: the first is the number of arguments provided by the user, the second is an array (possibly) of the arguments that were provided, and the third is where you need to put the answer.
-
Thanks for quick answer. But I still don't know how to do that, because I am new in VC++.
They said that it is possible to use multiple functions with @USER by writing and compiling each function as a
separate subroutine and taking an argument to @USER as the index number of the subroutine that you
want to branch to.
I am interested how to do that.
Thanks in advance.
-
A web forum is not somewhere where you can learn C++ from scratch.
"They said that it is possible to use multiple functions with @USER by writing and compiling each function as a
separate subroutine and taking an argument to @USER as the index number of the subroutine that you
want to branch to."
This is trivial -- you just call the function you want to call, based on the first parameter. If the first parameter is 1, you call function_A. If the first parameter is 2, you call function_B. This is more-or-less the second thing you do when you are learning functions. So: go forth and learn C++.