Unable to find an entry point when calling C++ dll in C#
Asked Answered
L

3

22

I am trying to learn P/Invoke, so I created a simple dll in C++

KingFucs.h:

namespace KingFuncs
{
    class KingFuncs
    {
    public:
        static __declspec(dllexport) int GiveMeNumber(int i);
    };
}

KingFuns.cpp:

#include "KingFuncs.h"
#include <stdexcept>

using namespace std;

namespace KingFuncs
{
    int KingFuncs::GiveMeNumber(int i)
    {
        return i;
    }
}

So it does compile, then I copied this dll into my WPF's debug folder, with code:

[DllImport("KingFuncDll.dll", EntryPoint = "GiveMeNumber", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern int GiveMeNumber(
              int i
              );

And calling it in button click:

private void Button_Click(object sender, RoutedEventArgs e)
{
    int num = GiveMeNumber(123);
}

But it gives me exception:

Unable to find an entry point named 'GiveMeNumber' in DLL 'KingFuncDll.dll'.

Really.... what have I done wrong... It obviously able to find the DLL, otherwise would be another exception. But my method name is exactly the same.... I can't think of other reason.

Leeke answered 11/4, 2012 at 15:58 Comment(2)
Please see my question here: #9850041Nila
I solved same question, and describe it at this post.Inebriety
I
44

You need to use extern "C" when you export your function so that you suppress C++ name mangling. And you also should not try to p/invoke to members of a class. Use free functions instead:

extern "C" {
    __declspec(dllexport) int GiveMeNumber(int i)
    {
        return i;
    }
}

On the managed side your DllImport attribute is all wrong. Don't use SetLastError which is for Win32 APIs only. Don't bother setting CharSet if there are not text parameters. No need for ExactSpelling. And the calling convention is presumably Cdecl.

[DllImport("KingFuncDll.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int GiveMeNumber(int i);
Incised answered 11/4, 2012 at 16:2 Comment(3)
Thanks, it worked. But it is not possible to call a function of a class? (This is my first time using extern "C", I thought I always need to define function within class in C++)Leeke
You do not need to define a function within a class in C++. Old fashioned C functions are just fine.Incised
Shall this extern "C"{} also be applied to structs?Regality
W
0

The problem is that you are declaring the C++ "function" inside a C++ class and are telling P/Invoke to use StdCall.

Try to declare a C++ function outside a class and and export it like you did. Then your code should work.

If you really must have a C++ function inside a class, take a look at CallingConvention.ThisCall. But then you are responsible for creating your unmanaged class instance and pass it as the first parameter of your P/Invoke call

Wolsky answered 11/4, 2012 at 16:6 Comment(0)
G
0

The entry point name of a dll file is given in .exp file which is found in debug folder where other source files are present. If dumpbin doesn't work you can try this.

Gromwell answered 13/4, 2017 at 8:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.