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.
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.
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.
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.
Most of the P/Invoke API is contained in two namespaces: System and System. Runtime.
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With