• 0

Creating a C DLL?


Question

I'm having trouble creating and calling a C dll using Visual C++ EE. The C file is really simple:

extern __declspec(dllexport) int retnum()
{

	return 0;
}

In the project I have a header file with:

__declspec(dllimport) int retnum();

The actual project is in manage C++(it's a windows form). I included the header file at the top and call the function:

retnum();

but I'm getting some errors from the linker:

1>control.h(3) : warning C4272: 'retnum' : is marked __declspec(dllimport); must specify native calling convention when importing a function.
1>Linking...
1>Sample.obj : error LNK2028: unresolved token (0A00000C) "int __clrcall retnum(void)" (?retnum@@$$FYMHXZ) referenced in function "private: void __clrcall Sample::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@Sample@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)
1>Sample.obj : error LNK2019: unresolved external symbol "int __clrcall retnum(void)" (?retnum@@$$FYMHXZ) referenced in function "private: void __clrcall Sample::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@Sample@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)

I haven't worked with dlls before, so I'm kind of lost. I havent specified were the dll is or what it's called anywhere in the main program, so I'm pretty sure that might be part of the problem, but I dont know how or were to do that.

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

  • 0

Just an update. changed the header to

#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>

#if defined DLL_EXPORT
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif

extern "C"
{
   DECLDIR __declspec(dllimport) int retnum();
}
#endif

and included it in the project that makes the dll as well. created a simple .def file:

LIBRARY Control
EXPORTS
retnum

and added the .lib file generated to the main project's properties -> linker -> additional dependencies.

All seems to be working, hopefully everything will continue to work as I build around this.

Link to comment
Share on other sites

  • 0

A few notes...

1) The key here was the extern "C" since that tells the compiler to use the C naming convention when exporting the function and when looking for the imported function. Your export and import must use the same convention (both CPP or both C). If your source file is C, then it must use the C convention, and if it's CPP, you have a choice between CPP or C convention.

2) There is no need for __declspec(dllexport) if you are using a .def file (which is recommended).

3) The __declspec(dllimport) declaration is mostly optional. All it does is let the compiler know, at each point where the function is called, that the function is going to be in a compile-time-linked DLL (vs. a delay-loaded DLL loaded vs. LoadLibrary or something that is not off in a DLL) so that it leaves room in the call instruction that it generates to call into the DLL import table and make life easier for the linker. If you omit it, things will work just fine--the linker will fix this for you by generating a pseudofunction that is called that calls into the import table--a trivial layer of indirection. Not that you should omit it, but just be aware that things work just fine without it.

Link to comment
Share on other sites

  • 0

OK. Just to update. I got rid of the .def file. In VS, i went to project -> properties -> Common Properties -> project dependencies then select the prject that will be using the DLL under "Project:" and tick the check box next to the project for the DLL.

I completely removed the header from the DLL's project.

I also titied up the header in the main project(the one using the DLL) quite a bit:

extern "C"
{
   __declspec(dllimport) int retnum();
}

I did this a few month ago, so I can't be sure if that's all I did to tiedy it up.

3) The __declspec(dllimport) declaration is mostly optional. All it does is let the compiler know, at each point where the function is called, that the function is going to be in a compile-time-linked DLL (vs. a delay-loaded DLL loaded vs. LoadLibrary or something that is not off in a DLL) so that it leaves room in the call instruction that it generates to call into the DLL import table and make life easier for the linker. If you omit it, things will work just fine--the linker will fix this for you by generating a pseudofunction that is called that calls into the import table--a trivial layer of indirection. Not that you should omit it, but just be aware that things work just fine without it.

Neat. Tried the header as:

extern "C"
{
   int retnum();
}

and it did work.

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.