unity3d EntryPointNotFoundException yet entryPoint exists - c#

I have a C/C++ unmanaged DLL that is working with the exception of a single method which causes an EntryPointNotFoundException
i'm setting up the DLL in c#
private const string dllname = "mydllname";
[DllImport(dllname)]
private static extern IntPtr CreateBridge();
[DllImport(dllname)]
private static extern void DestroyBridge(IntPtr context);
[DllImport(dllname)]
private static extern int getChannels(IntPtr context);
[DllImport(dllname)]
private static extern void setUpdate(IntPtr context, IntPtr values);
and then calling the method
IntPtr updatePtr = Marshal.AllocHGlobal(Marshal.SizeOf(update));
Marshal.StructureToPtr(update, updatePtr, true);
setUpdate(context, updatePtr);
Before I'm calling setUpdate(context, updatePtr) I'm sucessfully calling CreateBridge() and getChannels(IntPtr context) so we know the DLL is present, that it is loaded and that other entryPoints can be called
But setUpdate(context, updatePtr) causes the exception EntryPointNotFoundException
the C definition is as follows
#define DLL_EXPORT __declspec(dllexport)
...
extern "C" {
DLL_EXPORT UnityBridge* CreateBridge();
DLL_EXPORT void DestroyBridge(const UnityBridge* _unitybridge);
DLL_EXPORT int getChannels(UnityBridge* _unitybridge);
DLL_EXPORT void setUpdate(UnityBridge* _unitybridge, Update* update);
}
What else can cause this exception?
EDIT #1
I checked with Dependency it is not being exported... this makes the question different, but any clues?

Related

C++ dll on C# OpenCV

I am creating a dll using C++ with OpenCV. This dll is going to be used on C#.
My c++ (dll) code has three functions:
extern "C"
{
bool x(Mat image, Mat gray, Point center)
{...}
}
extern "C"
{
bool y(Mat image. Mat gray, Point center)
{...}
}
extern "C"
{
__declspec(dllexport)
int main (const char *cam1 ,int blur)
{...}
}
main function receives a string and an int from the C# code.
In C# I have:
[DllImport("mydll.dll")]
public static extern int main(string path, int blur);
How should I declare the other functions on C# knowing they have arguments with types like Mat and Point?
I did as Owuor suggested and it works.
My C++ bool functions are now
extern "C"
{
bool x(Mat *image, Mat *gray, Point *center)
{...}
}
extern "C"
{
bool y(Mat *image, Mat *gray, Point *center)
{...}
}
on C# I have
[DllImport("mydll.dll")]
public static extern int main(string path, int blur);
[DllImport("mydll.dll")]
public static extern bool (IntPtr ptr1, IntPtr ptr1, IntPtr ptr1);

how to display in messagebox a C function from C# with a WCHAR*

I'm building a C# application that loads a C++ library.
I call functions from that C++ DLL. I use below function to display input string.
c++ dll:
wchar_t* Test_EchoString( wchar_t *InputStr )
{
String HWStr = String( InputStr );
return HWStr.c_str();
}
c# code:
[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int _Test_EchoString([MarshalAs(UnmanagedType.LPWStr)] string s);
private void echo_string_Click(object sender, RoutedEventArgs e)
{
string upn = "aaaaa";
_Test_EchoString(upn);
MessageBox.Show(_Test_EchoString(upn).ToString());
}
I get in messagebox number 18666252 but i want to get a string from _Test_EchoString().
You have a pair of problems in your code:
in your C# you defined _Test_EchoString as public static extern int _Test_EchoString, so when you execute it, the returned value will be the address of the first character of the string HWStr.c_str().
And here it shows another problem, as anderas said, you are returning an invalid pointer, because HWStr.c_str() returns the pointer to the current value of the std::wstring object, so it is valid as long that the wstring is valid, so when the method Test_EchoString ends its execution it is no more valid(because HWStr is destroyed).
There are different ways to fix this problems, I'm going to show you two of these:
1) The first is to allocate the memory you want to return in the Heap and free it later with another call:
static wchar_t *Test_EchoStringResult;
extern "C" __declspec(dllexport) const wchar_t * Test_EchoStringNew(const wchar_t *InputStr)
{
std::wstring HWStr(InputStr);
HWStr += L" something";
Test_EchoStringResult = new wchar_t[HWStr.length() + sizeof(wchar_t)];
HWStr.copy(Test_EchoStringResult, HWStr.length());
Test_EchoStringResult[HWStr.length()] = L'\0';
return Test_EchoStringResult;
}
extern "C" __declspec(dllexport) void Test_EchoStringDelete()
{
delete[] Test_EchoStringResult;
}
And this is the usage in C#:
[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern IntPtr Test_EchoStringNew(string foo);
[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void Test_EchoStringDelete();
public void foo()
{
string result = Marshal.PtrToStringAuto(Test_EchoStringNew("test"));
MessageBox.Show(result.ToString());
Test_EchoStringDelete();
}
To me, this looks pretty ugly, so I'd prefer to use another pattern
2) Passing a callback to the C method and pass to this method HWStr.c_str() when HWStr is still valid:
extern "C" __declspec(dllexport) void Test_EchoString(const wchar_t *InputStr, void (*callback)(const wchar_t*))
{
std::wstring HWStr(InputStr);
HWStr += L" something";
callback(HWStr.c_str());
}
And here is the C# usage:
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public delegate void myCallback(string toShow);
[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern void Test_EchoString(string foo, myCallback callback);
public void foo()
{
Test_EchoString("test", callback);
}
void callback(string toShow)
{
MessageBox.Show(toShow);
}

the function LoadLibrary from kernel32.dll returns zero in Asp web application

I'am going to use a kernel32 dll in asp.net web application. This is the code:
//DllGetClassObject function pointer signature
private delegate int DllGetClassObject(ref Guid ClassId, ref Guid InterfaceId, [Out, MarshalAs(UnmanagedType.Interface)] out object ppunk);
//Some win32 methods to load\unload dlls and get a function pointer
private class Win32NativeMethods
{
[DllImport("kernel32.dll", CharSet=CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string lpFileName);
}
public string GetTheDllHandle (dllName)
{
IntPtr dllHandle = Win32NativeMethods.LoadLibrary(dllName); // the dllHandle=IntPtr.Zero
return dllHandle.ToString();
}
The problem that when I call my function GetTheDllHandle, the dllHandle return zero
Did anybody out there made something similar? Or does anybody have any suggestions?
Returning 0 while loading DLLs is coming due to several reasons like , DLL is not there on specified path or DLLs is not supported with platform or dependent dlls are not loaded before you build your native DLL. so you can track these errors by set true for SetLastError property
DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
public string GetTheDllHandle (dllName)
{
IntPtr dllHandle = Win32NativeMethods.LoadLibrary(dllName); // the dllHandle=IntPtr.Zero
if (dllHandle == IntPtr.Zero)
return Marshal.GetLastWin32Error().ToString(); // Error Code while loading DLL
else
return dllHandle.ToString(); // Loading done !
}

Marshalling PDouble (C# -> Delphi)

I've got an unmanaged DLL file written in Delphi, containing a function with the following definition:
function F(tgran: integer; inputs: PDouble; goutp, outputs, toutp: PDouble): integer; stdcall; external 'mydll.dll';
I've written an Adapter in C# that should help me consume it.
[UnmanagedFunctionPointer(APIAdapter.Convention)]
public delegate int FDelegate(int tgran, IntPtr inputs, IntPtr goutp, IntPtr outputs, IntPtr toutp);
public class APIAdapter : IDisposable
{
public const string DllName = "mydll.dll";
public const CallingConvention Convention = CallingConvention.StdCall;
public FDelegate F;
[DllImport("kernel32")]
private static extern IntPtr LoadLibrary(string lpLibFileName);
[DllImport("kernel32")]
private static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll")]
private static extern IntPtr GetProcAddress(IntPtr hModule, String procname);
private IntPtr _dllHandle;
public APIAdapter()
{
_dllHandle = LoadLibrary(DllName);
F = (FDelegate)GetFunction<CalcCavSpDelegate>("F");
}
private Delegate GetFunction<T>(string procName)
{
IntPtr procAddress = GetProcAddress(_dllHandle, procName);
return Marshal.GetDelegateForFunctionPointer(procAddress, typeof(T));
}
~APIAdapter()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
{
}
while (FreeLibrary(_dllHandle))
{
}
}
}
The usage is pretty straightforward:
using(var api = new APIAdapter())
{
// Call API functions
}
The problem is an AccessViolationException that happens within the DLL file.
I've tried to pass the PDouble variables as double[], double* (unsafe code), IntPtr. It's the same story regardless of the method I choose. I've tried to substantially increase the size of the arrays passed in to exclude errors with array indexing - AccessViolation exception again.
What is the proper way of passing a PDouble into an unmanaged Delphi DLL file?
I think you can do away with all the LoadLibrary, GetProcAddress and FreeLibrary complexity by simply using DllImport attribute. Though, I can say that I am not aware about any specific reason of why you chose to go this way.
Anyway, you can simply include ref double doubleArg in your declaration to pass PDouble. There should be no need of IntPtr here.

C# Error Finding Method in DLLImport

I have a C++ assembly that I am importing using DLLImport.
I am attempting to call its method:
namespace Testing
{
class Test{
int Run(char* filePath, bool bEntry, double duration){//code}
};
}
by
[DllImport(dllName, CharSet = CharSet.Auto)]
public static extern int Run(string filePath, bool bEntry, double duration)
);
When I call its method, I get the error message:
Unable to find an entry point named Run in dll
The "Run" looks to be a non-static class method. Although, it's possible to call such methods from C# this is not the primary use-case. It would be way easier to consume it from .NET if you expose it via COM, or at-least as a plain C interface:
extern "C" __declspec(dllexport) void* Testing_Test_Create();
extern "C" __declspec(dllexport) void Testing_Test_Destroy(void* self);
extern "C" __declspec(dllexport) int Testing_Test_Run(void* self, char* filePath, bool bEntry, double duration);
And here is a sample how to call C++ class methods from C#:
// Test.cpp in NativeLib.dll
namespace Testing
{
class __declspec(dllexport) Test
{
public:
explicit Test(int data)
: data(data)
{
}
int Run(char const * path)
{
return this->data + strlen(path);
}
private:
int data;
};
}
// Program.cs in CSharpClient.exe
class Program
{
[DllImport(
"NativeLib.dll",
EntryPoint = "??0Test#Testing##QAE#H#Z",
CallingConvention = CallingConvention.ThisCall,
CharSet = CharSet.Ansi)]
public static extern void TestingTestCtor(IntPtr self, int data);
[DllImport(
"NativeLib.dll",
EntryPoint = "?Run#Test#Testing##QAEHPBD#Z",
CallingConvention = CallingConvention.ThisCall,
CharSet = CharSet.Ansi)]
public static extern int TestingTestRun(IntPtr self, string path);
static void Main(string[] args)
{
var test = Marshal.AllocCoTaskMem(4);
TestingTestCtor(test, 10);
var result = TestingTestRun(test, "path");
Console.WriteLine(result);
Marshal.FreeCoTaskMem(test);
}
}
Entry point names might be different for your build configuration/compiler, so use dumpbin utility to obtain them. Again, this is just a proof of concept, in real code it would be better to use COM.
See here: http://dotnetperls.com/dllimport
I'm not sure this will help if the function is a member of a class, but to locate the entry point by name, not ordinal, you'll need a .def file in your dll..
LIBRARY mylib
Run #1

Categories