Calling Functions in a Dll from C++

Calling functions in a DLL from C++

There are many ways to do this but I think one of the easiest options is to link the application to the DLL at link time and then use a definition file to define the symbols to be exported from the DLL.

CAVEAT: The definition file approach works bests for undecorated symbol names. If you want to export decorated symbols then it is probably better to NOT USE the definition file approach.

Here is an simple example on how this is done.

Step 1: Define the function in the export.h file.

int WINAPI IsolatedFunction(const char *title, const char *test);

Step 2: Define the function in the export.cpp file.

#include <windows.h>

int WINAPI IsolatedFunction(const char *title, const char *test)
{
MessageBox(0, title, test, MB_OK);
return 1;
}

Step 3: Define the function as an export in the export.def defintion file.

EXPORTS    IsolatedFunction          @1

Step 4: Create a DLL project and add the export.cpp and export.def files to this project. Building this project will create an export.dll and an export.lib file.

The following two steps link to the DLL at link time. If you don't want to define the entry points at link time, ignore the next two steps and use the LoadLibrary and GetProcAddress to load the function entry point at runtime.

Step 5: Create a Test application project to use the dll by adding the export.lib file to the project. Copy the export.dll file to ths same location as the Test console executable.

Step 6: Call the IsolatedFunction function from within the Test application as shown below.

#include "stdafx.h"

// get the function prototype of the imported function
#include "../export/export.h"

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// call the imported function found in the dll
int result = IsolatedFunction("hello", "world");

return 0;
}

Calling a dll function from C++

There seems to be some confusion here. Adding a file to the linker input is for statically-linked libraries (.lib on Windows). With statically-linked libraries, the code is just copied into your program at compile time. Dynamically-linked libraries (.dll in Windows) reside in different files (the DLLs) and are loaded by your program when you run it. To access a function in a dll, there's two main methods:

  • Use dllimport, similarly to how you exported the functions with dllexport

  • Load the DLL using LoadLibrary, then get a pointer to your function with GetProcAddress. If you're using this method, another thing you should note is that you should likely use extern "C" on functions you're exporting to avoid name mangling. If you're having issues finding the function with GetProcAddress, you can use Dependency Walker to examine the function names inside the DLL - they may be modified slightly depending on the calling convention used.

(How) can a dll call a function that is implemented in its loading program?

Since you are using late binding for your .dll, you might do the same thing for function defined in the executable. Just call GetProcAddress in the same way, using this process handle (as it is already in the address space). Here is some (pseudo) code:

auto proc = GetModuleHandle(nullptr);
auto get_e = reinterpret_cast<float (*) ()>(GetProcAddress(proc, "get_e"));

How to call C DLL functions C++/CLI

OK, so "WPF with C++" is not a language. WPF is a .NET library. C++/CLI is the language you are writing in.

Calling C dlls from C++/CLI is "pretty darn easy", depending on how the DLL was exported. You can either use the .NET libraries to do this, or the C libraries (I suggest the C libraries). There are two ways to link to a dll: implicit linking or explicit linking.

Implicit linking is much cleaner, imho. But you require access to a header file (Edit: possibly with declspec decorations, see BenVoigt's notes below) and a .lib file. If you have any of these, simply add the .lib file to the Additional Dependencies (right-click project->properties->Configuration Properties->Linker->Input) and add the header file path to the include (right-click project->properties->Configuration Properties->C/C++->General). Then you can include the header file (props to metacubed for mentioning this) as an extern "C" header file:

extern "C"
{
#inlude "c_header.h"
}

(this is because C++ does name-mangling so that you can have overloading & namespaces & classes and stuff. It'll interpret your C header file as a C++ header file (and mangle all your names) if you don't use the extern "C")

http://msdn.microsoft.com/en-us/library/d14wsce5.aspx

Or you can link explicitly

http://msdn.microsoft.com/en-us/library/784bt7z7.aspx
http://msdn.microsoft.com/en-us/library/zzk20sxw.aspx

But I suspect that figuring out that you're using C++/CLI, that'll tell you what to google. (Though C++ answers will work for you too).

For the .NET way, an easy trick is to look up the C# call (please note that this is also explicit linking, and thus doesn't require the .lib file and headers).

http://msdn.microsoft.com/en-us/library/eyzhw3s8.aspx

Now the tricky bit is that if you're using C++/CLI and want to get your fancy managed classes into C form, you'll have to marshal the code. Here is a handy link to a tabel that shows you how.

http://msdn.microsoft.com/en-us/library/ac7ay120%28vs.71%29.aspx

cannot call function from a dll

You are not marking the method (or class) as dllexport/dllimport. In your DLL project settings, make sure COMPILING_MY_DLL is defined. Assuming the paths to the DLL are correct when running the app, everything should work fine.

#ifndef DLL_SAMPLE
#define DLL_SAMPLE

#ifdef COMPILING_MY_DLL
# define MY_DLL_EXPORT __declspec(dllexport)
#else
# define MY_DLL_EXPORT __declspec(dllimport)
#endif

#include <iostream>

class A
{
public:
MY_DLL_EXPORT static void a();
};

#endif

Call function from DLL?

Add the DLL via the solution explorer - right click on references --> add reference then "Browse" to your DLL - then it should be available.

Call function in C++ dll from C#

long in C maps to int in C#. And char is ANSI, so you need to specify UnmanagedType.LPStr. The Result appears to be an out parameter, for which you will need to pre-assign a buffer (size unknown?) and pass it as StringBuilder

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MyFunction(
ref int Code,
int Number,
[MarshalAs(UnmanagedType.LPStr)]
string Reference,
[MarshalAs(UnmanagedType.LPStr), Out]
StringBuilder Result);

Use it like this

var buffer = new StringBuilder(1024); // or some other size
MyFunction(ref myCode, myNumber, myReference, buffer);


Related Topics



Leave a reply



Submit