Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up a C++ function so that it can be used by p/invoke?

Hopefully this is a brainlessly easy question, but it shows my lack of expertise with C++. I'm a C# programmer, and I've done extensive work with P/Invoke in the past with other people's C++/C dlls. However, this time I've decided to write a wrapper C++ dll (unmanaged) myself, and am then calling my wrapper dll from C#.

The problem I am immediately running into is that I am unable to define a C++ function that can be found by p/invoke. I don't know what the syntax for this is, but here's what I'm trying so far:

extern bool __cdecl TestFunc()
{
  return true;
}

Originally I simply had this, but it did not work either:

bool TestFunc()
{
  return true;
}

And then on the C# side, I have:

    public const string InterfaceLibrary = @"Plugins\TestDLL.dll";

    [DllImport( InterfaceLibrary, CallingConvention = CallingConvention.Cdecl,
        EntryPoint = "TestFunc" ), SuppressUnmanagedCodeSecurity]
    internal static extern bool TestFunc();

Everything compiles, but when I execute this C# p/invoke call, I get a System.EntryPointNotFoundException: Unable to find an entry point named 'TestFunc' in DLL 'Plugins\TestDLL.dll'.

Surely this must be something incredibly simple on the C++ end that I just don't know the syntax for.

like image 625
Chris McElligott Park Avatar asked Oct 07 '09 20:10

Chris McElligott Park


People also ask

How does PInvoke work?

P/Invoke is the technique a programmer can use to access functions in these libraries. Calls to functions within these libraries occur by declaring the signature of the unmanaged function within managed code, which serves as the actual function that can be called like any other managed method.

How do I call C++ code from C#?

2. If you want to use C++ in c# code directly, you can create a CLR(C++/CLI) project, then you can write c++ and c# code in the same project.

What is extern C?

extern "C" specifies that the function is defined elsewhere and uses the C-language calling convention. The extern "C" modifier may also be applied to multiple function declarations in a block. In a template declaration, extern specifies that the template has already been instantiated elsewhere.

What overarching namespace provides PInvoke to net?

Most of the P/Invoke API is contained in two namespaces: System and System. Runtime.


2 Answers

You'll want to use extern "C" as well as __declspec(export), like so:

extern "C" _declspec(dllexport)  bool TestFunc()
{
    return true;
}

For full details, see MSDN on Marshalling Types.

like image 164
Reed Copsey Avatar answered Sep 28 '22 11:09

Reed Copsey


Extending Reed's correct answer.

Another issue you can run into when exposing a C++ function via PInvoke is using invalid types. PInvoke can really only support marshalling of primitive types and plain old data struct / class types.

For example, suppose TestFunc had the following signature

void TestFunc(std::string input);

Even adding extern "C" and __declspec(dllexport) would not be enough to expose the C++ function. Instead you would need to create a helper function which exposed only PInvoke compatible types and then called into the main function. For example

void TestFunc(const std::string& input) { ... }

extern "C" _declspec(dllexport)  void TestFuncWrapper(char* pInput) {
  std::string input(pInput);
  TestFunc(input);
}
like image 22
JaredPar Avatar answered Sep 28 '22 13:09

JaredPar