I'm trying to use a C++ unmanaged dll in a C# project and I'm getting an error when trying to call a function that says that entry point cannot be found.
public class Program
{
static void Main(string[] args)
{
IntPtr testIntPtr = aaeonAPIOpen(0);
Console.WriteLine(testIntPtr.ToString());
}
[DllImport("aonAPI.dll")]
public static extern unsafe IntPtr aaeonAPIOpen(uint reserved);
}
Here is the dumpbin for the function:
5 4 00001020 ?aaeonAPIOpen##YAPAXK#Z
I changed the dll import to [DllImport("aonAPI.dll", EntryPoint="?aaeonAPIOpen")] and [DllImport("aonAPI.dll", EntryPoint="_aaeonAPIOpen")] and no luck.
Using the undname.exe utility, that symbol demangles to
void * __cdecl aaeonAPIOpen(unsigned long)
Which makes the proper declaration:
[DllImport("aonAPI.dll", EntryPoint="?aaeonAPIOpen##YAPAXK#Z",
ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr aaeonAPIOpen(uint reserved);
It looks like the function you're trying to call is compiled as a C++ function and hence has it's name mangled. PInvoke does not support mangled name. You need to add an extern "C" block around the function definition to prevent name mangling
extern "C" {
void* aaeonAPIOpen(uint reserved);
}
Related
my c# part
[DllImport("asdf.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
unsafe extern public static int CompareDB(string[] filename);
Below is c++ part
extern "C" __declspec(dllexport)int CompareDB(char** name)
{
CString filename="It is already assigned in previous code"
strcpy(name[1], (const char *)fileName);
}
Error is related with attempting to read or write protected memory.
Somebody help me please.
I'm trying to do the pocketsphinx tutorial in C# using pinvoke but get an AccessViolationException when I try to decode using ps_decode_raw().
IntPtr ps = PocketSphinx.ps_init(config);
IntPtr fh = Win32Util.fopen(#"goforward.raw", "rb");
int rv = PocketSphinx.ps_decode_raw(ps, fh, "goforward", -1);
The functions are wrapped as follows
//ps_decoder_t* ps_init(cmd_ln_t* config)
[DllImport("pocketsphinx.dll",
SetLastError = true,
CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr ps_init(
IntPtr config);
//int ps_decode_raw(ps_decoder_t *ps, FILE *rawfh, char const *uttid, long maxsamps);
[DllImport("pocketsphinx.dll",
SetLastError = true,
CallingConvention = CallingConvention.Cdecl)]
public extern static int ps_decode_raw(
IntPtr ps,
IntPtr rawfh,
[MarshalAs(UnmanagedType.LPStr)] string uttid,
int maxsamps);
[DllImport("msvcrt.dll",
SetLastError = true,
CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr fopen(
[MarshalAs(UnmanagedType.LPStr)] string _Filename,
[MarshalAs(UnmanagedType.LPStr)] string _Mode);
I wrapped C's fopen as well just because it was the quickest way I can think of implementing the tutorial.
I tried calling cmd_ln_retain on ps to make sure that ps wasn't causing the problem. (it wasn't). I also removed my debug code in the above.
I'm pretty sure something is up with the fopen but I'm not sure what.
Someone asked for the pocketsphinx log. https://justpaste.it/h52t
You don't check for errors anywhere. And it's wrong to set SetLastError to true for these functions. They won't call SetLastError.
Your big problem though is that the library uses a particular instance of the C runtime, depending on how you built it. And your fopen import is from a different instance of the C runtime.
You'll need to add some code to the library that exposes functions to create and destroy FILE* objects. By doing that you'll get a FILE* made by the correct runtime.
I have the following C++ function exported in a DLL:
extern "C" __declspec(dllexport) bool GetResolutionArray(int32_t adapterIndex, int32_t outputIndex, uint32_t arrayLength, Resolution outResolutionArr[]) {
memcpy_s(
outResolutionArr,
sizeof(Resolution) * arrayLength,
RENDER_COMPONENT.GetResolutionArray(adapterIndex, outputIndex),
RENDER_COMPONENT.GetOutput(adapterIndex, outputIndex).NumResolutions * sizeof(Resolution)
);
return true;
}
And, the matching extern function declaration in C#:
[DllImport(InteropUtils.RUNTIME_DLL, EntryPoint = "GetResolutionArray", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool _GetResolutionArray(int adapterIndex, int outputIndex, uint resolutionArrayLength, [MarshalAs(UnmanagedType.LPArray), In, Out] ref Resolution[] resolutions);
However, when I attempt to use this function as below, the program crashes with a FatalExecutionEngineError (indicating I corrupted something somewhere I guess) (error code 0xc0000005, i.e. access violation):
Resolution[] resolutions = new Resolution[outOutputDesc.NumResolutions];
if (!_GetResolutionArray(outAdapterDesc.AdapterIndex, outOutputDesc.OutputIndex, (uint) resolutions.Length, ref resolutions)) {
EnginePipeline.TerminateWithError("Internal engine call failed: _GetResolutionArray");
}
I strongly suspect that my call to memcpy_s is causing the access violation, but I can't see how or why, and I therefore reason that perhaps the marshalling is going wrong somewhere.
Thank you.
The array parameter is declared incorrectly. A C# array is already a reference and so you don't need the ref. Declare it like this:
[DllImport(InteropUtils.RUNTIME_DLL, EntryPoint = "GetResolutionArray",
CallingConvention = CallingConvention.Cdecl)]
internal static extern bool _GetResolutionArray(int adapterIndex,
int outputIndex, uint resolutionArrayLength, Resolution[] resolutions);
i have a simple function in c++ (not a method of a class)
__declspec(dllexport) extern "C" void __stdcall TestFunc();
i try to call it from c#:
[DllImport("ImportTest.dll")]
public static extern void TestFunc();
...
TestFunc();
It throws an "entry point could't be found" exception.
Whats wrong?
Thank you for helping me :)
Try (guessing, that DLL is written in VS)
extern "C" __declspec(dllexport) void __stdcall TestFunc();
That's:
__declspec(dllexport) to notify compiler, that this function is to be exported from the DLL;
extern "C" mainly to prevent function name decorations;
__stdcall, because this is default calling convention if you specify none in [DllImport] directive.
In the future, you can check if your function is exported from DLL using Dll export viewer.
In C++ function , at header(if your function is declared in header) add
extern "C" _declspec(dllexport) void TestFunc();
at the function definition use
_declspec(dllexport) void TestFunc()
{
}
At C# side,you need to declare a function like
[DllImport(#"ImportTest.dll",
EntryPoint = "TestFunc",
ExactSpelling = false,
CallingConvention = CallingConvention.Cdecl)]
static extern void NewTestFunc()
Now use , NewTestFunc()
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.
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);
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
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.