- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
This is a follow up question to my last post.
Previously, I had a problem linking the function
dgetrf in C++ using Visual Studio 6 with the stdcall calling
convention. The solution to this problem as Tim pointed
out was to call the function with capital letters, DGETRF.
Then it links and runs with no problem.
However, now that I have the matrix in LU form, I want to
solve it. So I tried calling the function DGETRS. When I
do this I get the same linking error, now with DGETRS:
HFTestRoutines.obj : error LNK2001: unresolved external symbol _DGETRS@36
../lib/mytests.dll : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
The call looks like this:
char tran = 'C';
int dm = 10;
int nrhs = 1;
int nchar = 1;
int info = l;
DGETRS(&tran, &dm, &nrhs, a, &dm, ipiv, rhs, &dm, &info);
where
a is the same matrix (*double) that goes into DGETRF;
ipiv is a *int of length 10 output by DGETRF;
rhs is a *double of length 10.
I have the vague sense that the problem might have something
to do with the different way that C and Fortran treat characters,
but I can't see why (even if this is the problem) the function
won't link.
(I tried all lowercase, and this does not work either).
Once again, any help would be greatly appreciated. I thought
this afternoon that these problems were behind me and now I feel
like I'm back at square one!
This is a follow up question to my last post.
Previously, I had a problem linking the function
dgetrf in C++ using Visual Studio 6 with the stdcall calling
convention. The solution to this problem as Tim pointed
out was to call the function with capital letters, DGETRF.
Then it links and runs with no problem.
However, now that I have the matrix in LU form, I want to
solve it. So I tried calling the function DGETRS. When I
do this I get the same linking error, now with DGETRS:
HFTestRoutines.obj : error LNK2001: unresolved external symbol _DGETRS@36
../lib/mytests.dll : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
The call looks like this:
char tran = 'C';
int dm = 10;
int nrhs = 1;
int nchar = 1;
int info = l;
DGETRS(&tran, &dm, &nrhs, a, &dm, ipiv, rhs, &dm, &info);
where
a is the same matrix (*double) that goes into DGETRF;
ipiv is a *int of length 10 output by DGETRF;
rhs is a *double of length 10.
I have the vague sense that the problem might have something
to do with the different way that C and Fortran treat characters,
but I can't see why (even if this is the problem) the function
won't link.
(I tried all lowercase, and this does not work either).
Once again, any help would be greatly appreciated. I thought
this afternoon that these problems were behind me and now I feel
like I'm back at square one!
Link Copied
9 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are correct and I am not certain I can help you at the moment. As I stated in an earlier note there is a difference between CVF interface and stdcall but I have not been able to put my hands on the documentation that differentiates the details.
Bruce
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The mkl_s.lib conforms with a modified version of stdcall which permits character strings to be called from Fortran. I suppose it shouldn't be too difficult to use the stdcall interface with older Windows C compilers, when calling functions which don't have a character string argument. Needless to say, there are limitations on this business of using ABIs which were obsoleted several years ago.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Bruce,
I think I've figured out what is going on. The
declaration of the function DGETRS in
mkl_lapack64.h is not quite right.
The declaration is
void DGETRS(char *trans,int *n,int *nrhs,double *a,int *lda,int *ipiv,double *b,int *ldb,int *info);
But looking around on the web, it seems that when a FORTRAN
function takes a character argument, the corresponding C call
must use two arguments: a *char, and then an int that says
how long the character string is. See for example
http://www.nag.co.uk/numeric/FLOLCH/chw3220da.html
So the declaration should be
void DGETRS(char *trans, int nchar, int *n,int *nrhs,double *a,int *lda,int *ipiv,double *b,int *ldb,int *info);
When I use this declaration, the program compiles and links.
I'm guessing all the declarations in mkl_lapack64.h and
mkl_lapack32.h that have character arguments might require this
change.
(I have not yet run the function to test the output, so
there could be more surprises lurking here).
Jeff
I think I've figured out what is going on. The
declaration of the function DGETRS in
mkl_lapack64.h is not quite right.
The declaration is
void DGETRS(char *trans,int *n,int *nrhs,double *a,int *lda,int *ipiv,double *b,int *ldb,int *info);
But looking around on the web, it seems that when a FORTRAN
function takes a character argument, the corresponding C call
must use two arguments: a *char, and then an int that says
how long the character string is. See for example
http://www.nag.co.uk/numeric/FLOLCH/chw3220da.html
So the declaration should be
void DGETRS(char *trans, int nchar, int *n,int *nrhs,double *a,int *lda,int *ipiv,double *b,int *ldb,int *info);
When I use this declaration, the program compiles and links.
I'm guessing all the declarations in mkl_lapack64.h and
mkl_lapack32.h that have character arguments might require this
change.
(I have not yet run the function to test the output, so
there could be more surprises lurking here).
Jeff
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Tim,
Thanks for the response. I just posted at note at the
same time as you again. Do you think that what
I propose in that note might work?
Jeff
Thanks for the response. I just posted at note at the
same time as you again. Do you think that what
I propose in that note might work?
Jeff
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jeff,
If you look at the name of the function in mkl_s.lib with something like dumpbin or nm you will see that the name is DGETRF@40. The "40" indicates the number of bytes needed to pass all the arguments with a 4 byte integer (address) needed for each paramater. However, if you count the number of parameters there are only 9 parameters so why "40" and not "36"? The answer is that a hidden integer is needed for each string indicating the length of the string. What I could not recall was which interface (stdcall or CVF) put those string lengths adjacent to the strings and which put them at the end of the list of parameters.
Bruce
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bruce, thanks for the response. If I understand it then,
the int corresponding to the string length either comes
after the character argument, or as the last argument -
but you don't recall which. I'll try both ways and see what happens.
Do you agree with my earlier point that one must
change the declaration in the .h file before compiling?
Also, here is an unrelated question that you or Tim might
be able to address.
I need to build my DLL as stdcall.
Does that mean that I must use the mk_s.lib to link.
That is, would something terrible happen if
I built my DLL using stdcall and tried to link to
the mk_c.lib?
Jeff
the int corresponding to the string length either comes
after the character argument, or as the last argument -
but you don't recall which. I'll try both ways and see what happens.
Do you agree with my earlier point that one must
change the declaration in the .h file before compiling?
Also, here is an unrelated question that you or Tim might
be able to address.
I need to build my DLL as stdcall.
Does that mean that I must use the mk_s.lib to link.
That is, would something terrible happen if
I built my DLL using stdcall and tried to link to
the mk_c.lib?
Jeff
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
mkl_s.lib should be set up with the string length argument immediately after the character string argument, as that was the default for the CVF compiler. If you supply a prototype for the C interface, you must make it agree with this scheme.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tim has already answered the question about where the string length belongs for the CVF interface.
We have made things easy for you to use dll. In the lib directory is a file mkl_s_dll.lib. If you link that into your program you will need the dlls in you path as all you will have linked in is the software to import the dlls. (We have equivalent functionality for cdecl - mkl_c_dll.lib).
Bruce
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tim, Bruce,
Thanks for your help on these points. I appreciate it.
Regards, Jeff
Thanks for your help on these points. I appreciate it.
Regards, Jeff

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page