1

I am having trouble getting this to work. I created a test solution(VS2015) with a c++ DLL Project, a c++ ConsoleApplication and a c# ConsoleApplication. Both Console Application call the a DLL function in their main method and print the result to the console. All projects build to the same directory.

This works fine in the c++ ConsoleApplication since I simply added a reference to the DLL-Project and included the header.

In the c# ConsoleApplication I cant get this to work. I know its unmanaged code and that I need to use DLLImport.

When I try wo run the c# app it raises a System.EntryPointNotFoundException on calling test(). And says the Entry point "test" could not be found.

So what am I doing wrong?

DLL.h
    #ifdef DLL_EXPORTS
    #define DLL_API __declspec(dllexport)
    #else
    #define DLL_API __declspec(dllimport)
    #endif

    DLL_API int test(void);

DLL.cpp
    #include "DLL.h"
    // This is an example of an exported function.
    DLL_API int test(void)
    {
        return 42;
    }

Which compiles to DLL.dll.

Programm.cs
    using System;
    using System.Runtime.InteropServices;

    namespace DLLTestCSharp
    {

        class Program
        {

            [DllImport("DLL.dll")]
            public static extern int test();

            static void Main(string[] args)
            {

                Console.WriteLine(test());

                Console.Read();
            }
        }
    }

Which compiles to DLLTestCSharp.exe.

All files are on the same path.

Nurfed
  • 139
  • 3
  • 13
  • 1
    It is because of C++ names' mangling. You need to mark your method with `extern "C"` or add a .def file with export names to your dll project. – Alex Skalozub Feb 03 '16 at 19:16
  • Do you mean I have to do the exporting/importing manually without the API macro? – Nurfed Feb 03 '16 at 19:27
  • API macro is okay, you only need to disable C++ mangling somehow. It can be done by either declaring a function in `extern "C"` block (or by adding `extern "C"` into API macros), or by providing an export name in a .def file. – Alex Skalozub Feb 03 '16 at 19:38
  • Well thanks! After changing the method in DLL.h from `DLL_API int test(void);` to `extern "C" DLL_API int test(void);` It compiled and executed correctly! But isnt there a way to achieve this with the right attribute on the c# method? – Nurfed Feb 03 '16 at 19:38
  • Alex Skalozub - Create an answer with the same content and i will flag it as solved – Nurfed Feb 03 '16 at 19:41
  • No, C# method cannot change the way a name is exported by dll. You only can specify a mangled name in an EntryPoint property of DllImport, but you'll need to update it every time you change function signature in a dll – Alex Skalozub Feb 03 '16 at 19:41

2 Answers2

1

I think your problem is, When we compile code in c/c++ and export functions, according to calling conventions we use, there is names like @Test0 and so on in export table. I say you download CffExplorer and see your export table of your dll. and then try to import with right name.

Vahid K.
  • 440
  • 4
  • 14
1

The entry point cannot be found because of C++ names' mangling. It encodes method names in a special unique manner to support overloading and templates.

To disable this behavior and export method name as is, you need to either mark your method with extern "C" (or put into extern "C" { } block), or add a .def file with export names to your dll project.

Usually it is done in a header file:

#ifdef __cplusplus
extern "C" {
#endif

DLL_API int test();

// other functions

#ifdef __cplusplus
}
#endif

This will work on all platforms.

Def file, on the other hand, is mostly Windows method. You add a ProjectName.def to your solution and place there exports list:

LIBRARY <libraryname>
EXPORTS
    test

More on MSDN

Alex Skalozub
  • 2,511
  • 16
  • 15