DLL inclusion

Hi, I am trying to use a method defined in a DLL Project, say, "Project A" and use it in "Project B".

The method's declaration, in Project A's header file, is:

 
extern "C"{__declspec(dllexport) matrix __cdecl getMatrixFromSubFile(setInt rows, std::string fn, int factor);}
,

and, it's implementation, defined in Project A's cpp.file, is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
extern "C"{
	__declspec(dllexport) matrix __cdecl getMatrixFromSubFile(setInt rows, std::string fn, int factor)
	{
		matrix ma;
		std::ifstream *f = new std::ifstream(fn);
		char a[10000];
		for (int i = 0; i < rows.intSet.size(); i++)
		{
			for (int j = 0; j <rows.intSet.at(i)*factor; j++)
			{
				if (j == rows.intSet.at(i)*factor -1)
				{
					f->getline(a, 10000);
					std::string szVec = std::string(a);
					avector curvec = szVectorToRealVec(szVec);
					ma.vectors.push_back(curvec);
					//f = new std::ifstream(fn);
					f->seekg(0, f->beg);
				}
				else
				{
					f->getline(a,10000);
				}
			}
		}
		f->close();
		delete f;
		return ma;
	}
}
.

Now, In "Project B", I go about getting an HINSTANCE handle to the DLL as follows:

 
HINSTANCE hGetProcIDDLLLINEAR_ALGEBRA = LoadLibrary(L"C:\\Users\\a\\Documents\\visual studio 2012\\Projects\\DLLs\\LINEAR_ALGEBRA\\LINEAR_ALGEBRA\\Debug\\LINEAR_ALGEBRA.dll");


This works.

Then, in the same file, further ownward in code, I do:

1
2
3
4
5
6
7
8
9
10
11
FARPROC lpfnGetProcessID;
lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLLLINEAR_ALGEBRA),"getMatrixFromSubFile"); 
	std::cout << GetLastError() << std::endl;
    /* 
       Define the Function in the DLL for reuse. This is just prototyping the dll's function. 
      A mock of it. Use "stdcall" for maximum compatibility. 
    */ 
    typedef matrix (__cdecl * pICFUNCGet_Matrix_From_Sub_File)(setInt rows, std::string fn, int factor); 

    pICFUNCGet_Matrix_From_Sub_File get_matrix_from_sub_file_P; 
    get_matrix_from_sub_file_P = pICFUNCGet_Matrix_From_Sub_File(lpfnGetProcessID); 


This usually works. However, in this case, line:
 
lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLLLINEAR_ALGEBRA),"getMatrixFromSubFile");


returns a NULL pointer, and the next line:

 
std::cout << GetLastError() << std::endl;

"couts"

"127" (i.e. error 127).

When compiling Project A (the DLL), I get a compiler warning:


1>c:\users\a\documents\visual studio 2012\projects\dlls\linear_algebra\linear_algebra\linear_algebra\LINEAR_ALGEBRA.h(41): warning C4190: 'getMatrixFromSubFile' has C-linkage specified, but returns UDT 'matrix' which is incompatible with C


So, I tried using "C++" linkage, instead. This eliminates the compiler warning in Project A, but the "result" in "Project B" is, unfortunately, unchanged: Above line:

 
lpfnGetProcessID = GetProcAddress(HMODULE (hGetProcIDDLLLINEAR_ALGEBRA),"getMatrixFromSubFile");


STILL returns a NULL pointer, and the error "127" is "couted".

Why is this happening, and, how can I work around it, so that I can use a DLL function from Project A in Project B, even though the function returns a User-Defined-Type ("matrix")? (i.e. incompatible with "C"-linkage, apparently).

This is on Windows 8, using Visual Studio 2012 IDE.

Thanks for any and all help, and explanations!

Thanks! :)

Hansaa :)




Last edited on
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx

ERROR_PROC_NOT_FOUND
127 (0x7F)
The specified procedure could not be found.


I'm sure you don't need to " extern "C" " your project if you only plan on using it in C++.

Anyways for the Visual Studio you need to use an Def file (Exports.def usually).

http://msdn.microsoft.com/en-us/library/aa278947(v=vs.60).aspx

Just create one from the VS, and it will look like this:


LIBRARY <Your library name here>
EXPORTS
<Function Name> @1
<Another Function Name> @2
<Yet Another Function Here> @3
...


This *should* do the trick.
Hmm, I WILL do this if I have to, but I was "hoping" on not having to use a DEF file, as it adds additional "overhead", in that, I need more files than if I don't need it (the "def"-file).

I was able to successfully do this with methods that return "C"-types (int, double, void), etc, WITHOUT .def-files.

But, again, with methods that return User-Defined-Types, this doesn't work, at least not with "C"-linkage. Then though, I wonder, why it doesn't work with C++ linkage? Maybe I do need the "C++"-linkage, but I am still wondering if this is POSSIBLE without an additional "def"-file.

I will definitely take a look at the URLS you posted, though! Thanks!!

Hansaaa :)
Last edited on
Anyways for the Visual Studio you need to use an Def file (Exports.def usually).

If you're using __declspec, you don't need a .def file for the simple case.

(It doesn't hurt if you can have both, and there are occasions when you must use a def file, eg. for ordinals)

But here, as GetProcAddress is being used, you need to use a def file to work round the name mangling (as you've already mentioned, extern "C" can not be used in this case as you're using C++ types)

To find out what the mangled name is, you need to dump the exports. This can be done by opening a Visual Studio command prompt and the using the linker like this:

link /dump /exports LINEAR_ALGEBRA.dll

(with a full path, if needed)

Then add (or edit) the def file to provide an alias for the function and then relink the DLL.

For me, my (minimal) def file ends up as:

1
2
EXPORTS
    getMatrixFromSubFile = ?getMatrixFromSubFile@@YA?AVmatrix@@V?$set@HU?$less@H@std@@V?$allocator@H@2@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@H@Z


You probably don't want to use the full, mangled name with GetProcAddress!

Andy
Last edited on
I usuallay use "Dependancy Walker" for this. This should work as well, right?

Here is the output of dep walker, on LINEAR_ALGEBRA.dll:

http://postimg.org/image/5v8izecml/

As you can see, it does export it (I have now switched to using "Extern "C++"", I.e. c++ linkage).

Would I need to use a "mangled" name to use this method?

I can also try a "Visual Studio Command Prompt", if this produces other results. But I am unsure on where to open/find it. I have Visual Studio 2012 Express Edition, and I can't find the VS Command prompt on my machine, so far.

It can't be found in Visual Studio->Tools, nor, doing a windows search of "Visual Studio": Only result is Visual Studio itself, not any indication of a command prompt. Not sure if there is a "Command Prompt" in the EXPRESS edition of VS? Anyone know?? :)
Last edited on
If you (a) don't want to use a def file or modify your function so it uses types which allow you to use extern "C" and (b) need to use GetProcAddress, then you will need to use the mangled name.

Note that the name mangling can change from compiler version to compiler version, so you'll need to use the name you get when you build the DLL.

Or you can use the ordinal (the value of 8 is from your depends.exe screenshot).

lpfnGetProcessID = GetProcAddress(hMod, (LPCSTR)MAKELONG(8, 0));

The danger with using an ordinal is that if you update you DLL and the order of the exports changes, then GetProcAddress will find the wrong function. So when you try to call it, your program will prob blow up!

Andy

PS I just mention the command prompt because it allowed you to dump the exports using the linker. Not so relevant if you've got the depends tool.

I think you're right about the developer command prompt being missing from the express edition. But you can open a regular command prompt and then run

C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\VsDevCmd.bat

Last edited on
So I guess I suggested the best suggestion.
But this thing of the MAKELONG is good to be known, thanks andywestken.
Beatiful! The "mangled" name works! Thanks to andy, and also EssGeEich, for suggestions and ideas!! :)
Topic archived. No new replies allowed.