I have written a DLL in dev C++. The DLL's name is "DllMain.dll" and it contains two functions: HelloWorld and ShowMe. The header file looks like this:
DLLIMPORT void HelloWorld();
DLLIMPORT void ShowMe();
And the source file looks like this:
DLLIMPORT void HelloWorld ()
{
MessageBox (0, "Hello World from DLL!\n", "Hi",MB_ICONINFORMATION);
}
DLLIMPORT void ShowMe()
{
MessageBox (0, "How are u?", "Hi", MB_ICONINFORMATION);
}
I compile the code into a DLL and call the two functions from C#. The C# code looks like this:
[DllImport("DllMain.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void HelloWorld();
[DllImport("DllMain.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void ShowMe();
When I call the function "HelloWorld" it runs well and pops up a messageBox, but when I call the function ShowMe an EntryPointNotFoundException occurs. How do I avoid this exception? Do I need to add extern "C" in the header file?
The following code in VS 2012 worked fine:
#include <Windows.h>
extern "C"
{
__declspec(dllexport) void HelloWorld ()
{
MessageBox (0, L"Hello World from DLL!\n", L"Hi",MB_ICONINFORMATION);
}
__declspec(dllexport) void ShowMe()
{
MessageBox (0, L"How are u?", L"Hi", MB_ICONINFORMATION);
}
}
NOTE: If I remove the extern "C" I get exception.
using System;
using System.Runtime.InteropServices;
namespace MyNameSpace
{
public class MyClass
{
[DllImport("DllMain.dll", EntryPoint = "HelloWorld")]
public static extern void HelloWorld();
[DllImport("DllMain.dll", EntryPoint = "ShowMe")]
public static extern void ShowMe();
}
}
things that helped:
The: extern "C" { function declarations here in h file } will disable C++ name encoding. so c# will find the function
Use __stdcall for the C declaration or CallingConvention.Cdecl in the
C# declaration
maybe use BSTR/_bstr_t as string type and use other vb types. http://support.microsoft.com/kb/177218/EN-US
download "PInvoke Interop Assistant" https://clrinterop.codeplex.com/releases/view/14120
paste function declaration from .h file in the 3rd tab = c#
declaration. replace with dll filename.
Related
I have written a DLL in dev C++. The DLL's name is "DllMain.dll" and it contains two functions: HelloWorld and ShowMe. The header file looks like this:
DLLIMPORT void HelloWorld();
DLLIMPORT void ShowMe();
And the source file looks like this:
DLLIMPORT void HelloWorld ()
{
MessageBox (0, "Hello World from DLL!\n", "Hi",MB_ICONINFORMATION);
}
DLLIMPORT void ShowMe()
{
MessageBox (0, "How are u?", "Hi", MB_ICONINFORMATION);
}
I compile the code into a DLL and call the two functions from C#. The C# code looks like this:
[DllImport("DllMain.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void HelloWorld();
[DllImport("DllMain.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void ShowMe();
When I call the function "HelloWorld" it runs well and pops up a messageBox, but when I call the function ShowMe an EntryPointNotFoundException occurs. How do I avoid this exception? Do I need to add extern "C" in the header file?
The following code in VS 2012 worked fine:
#include <Windows.h>
extern "C"
{
__declspec(dllexport) void HelloWorld ()
{
MessageBox (0, L"Hello World from DLL!\n", L"Hi",MB_ICONINFORMATION);
}
__declspec(dllexport) void ShowMe()
{
MessageBox (0, L"How are u?", L"Hi", MB_ICONINFORMATION);
}
}
NOTE: If I remove the extern "C" I get exception.
using System;
using System.Runtime.InteropServices;
namespace MyNameSpace
{
public class MyClass
{
[DllImport("DllMain.dll", EntryPoint = "HelloWorld")]
public static extern void HelloWorld();
[DllImport("DllMain.dll", EntryPoint = "ShowMe")]
public static extern void ShowMe();
}
}
things that helped:
The: extern "C" { function declarations here in h file } will disable C++ name encoding. so c# will find the function
Use __stdcall for the C declaration or CallingConvention.Cdecl in the
C# declaration
maybe use BSTR/_bstr_t as string type and use other vb types. http://support.microsoft.com/kb/177218/EN-US
download "PInvoke Interop Assistant" https://clrinterop.codeplex.com/releases/view/14120
paste function declaration from .h file in the 3rd tab = c#
declaration. replace with dll filename.
I implemented two functions in Visual C++ DLL project. These functions will be called from C# program.
These are my functions in C++ DLL (not the actual implementation). mytest.cpp project.
extern "C"
{
__declspec(dllexport)void print_DB(null *head)
{
/*print all nodes*/
return;
}
__declspec(dllexport)void* add_node(void *head, int data)
{
/*Add node to data base*/
return (head);
}
}
My C# program is as follows.
namespace example
{
class test
{
[DllImport("mytest.dll", CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern void* add_node(void *head, int data);
unsafe public static extern void print_DB(void *head);
unsafe static void Main(string[] args)
{
/*initilialization*/
head = add_node(head, a)
head = add_node(head, b)
head = add_node(head, c)
printDB(head);
}
}
}
I am able to use on function at a time. ie, If I comment print_DB() deceleration from C# program, add_node() functionality is working. If I commented add_node() function print_DB() function is working. In this way both functions are giving the expected results.
If I am using both functions together, the function which is declared at the end is giving error as below. Invoking or not invoking the functions don't have any effect on the behavior.
Could not load type 'ConsoleApplication2.Program' from assembly
'ConsoleApplication2, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null' because the method 'printDB' has no
implementation (no RVA).
where "ConsoleApplication2.Program" is the name of my C# program.
If I change the order of the functions deceleration, will get same error for the other function.
These are my questions
1)I am new to C# programming. my expectation is this functions should work irrespective of how many functions we declared in the C# program. Is this is a expected behavior?
2)If it not the expected behavior What am I doing wrong?
The DllImport line must be present before every imported function declaration, like so:
namespace example
{
class test
{
[DllImport("mytest.dll", CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern void* add_node(void *head, int data);
[DllImport("mytest.dll", CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern void print_DB(void *head);
unsafe static void Main(string[] args)
{
/*initilialization*/
head = add_node(head, a)
head = add_node(head, b)
head = add_node(head, c)
printDB(head);
}
}
}
Hi I have create c++ function as
void MyClass::GetPRM(BSTR BString)
{
//----
}
In C# the dll interface looks like:
GetPRM(char* BString)
My question is how can I pass string as char* from c# to c++ dll?
I have tried doing
void MyClass::GetPRM(std::string BString) but no luck.
Any Suggestions
You should be able to use
[DllImport("mycppdll", EntryPoint="MyClass_GetPRM")]
extern static void GetPRM([MarshalAs(UnmanagedType.BStr)] string BString)
However, that doesn't take into account C++ name-mangling, nor your C++ method's this pointer if that method is not declared static.
On the C side, you may need a wrapper function like this:
extern "C" __declspec(dllexport) void __stdcall
MyClass_GetPRM(BSTR BString)
{
MyClass::GetPRM(BString);
}
which would require adaptation of the C# declaration to match the exported name:
[DllImport("mycppdll", EntryPoint="MyClass_GetPRM")]
extern static void GetPRM([MarshalAs(UnmanagedType.BStr)] string BString)
It looks likes this
#include <stdio.h>
#define __dllexport extern "C" __declspec(dllexport)
class PureVirtual
{
public:
virtual void Foo() = 0;
};
class ImplPureVirtual : public PureVirtual
{
public:
void Foo()
{
printf("Moo");
}
};
__dllexport PureVirtual* GetPV();
In implementation:
#include "ManagedClass.h"
PureVirtual* impl = new ImplPureVirtual;
__dllexport PureVirtual* GetPV()
{
return impl;
}
It compiled as TestFoo.dll, Then in C#
class Program
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string strFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string strProcName);
static void Main(string[] args)
{
var ptrLib = LoadLibrary("TestFoo.dll");
if (ptrLib != IntPtr.Zero)
{
var ptrAddr = GetProcAddress(ptrLib, "GetPV");
if (ptrAddr != IntPtr.Zero)
// Now we have the pointer object, what should I do next?
}
Console.ReadLine();
}
}
I think it's a pretty good problem, that if a software company released their unmanaged API to the public(with only pure virtual method), and if we could control the wisdom of C++ abstractive and polymorphism, then we could make it into managed and have several benefit! Such as Garbage control, generics, and a wide choices of references and libraries.
You would also need to define an extern "C" function for each virtual member; managed code cannot call unmanaged C++ exports in an easy or portable way due to C++ name mangling. For example:
__dllexport void PureVirtual_Foo(PureVirtual * pv)
{
pv->Foo();
}
Also, consider that you need to catch C++ exceptions in the extern "C" wrappers, because an uncaught exception can skip over managed stack frames, causing the CLR to get into a bad state.
I would strongly suggest that you look into using SWIG. It is able to automatically generate these wrappers for you.
Note that you do not need to use LoadLibrary() etc., you can just P/Invoke the function:
[DllImport("TestFoo")]
public static extern IntPtr GetPV();
Likewise, to call the virtual method given my example wrapper:
[DllImport("TestFoo")]
public static extern void PureVirtual_Foo(IntPtr pv);
Then you could call the virtual method like this:
PureVirtual_Foo(GetPV());
I have a C# application that calls functions in a DLL written in C++. The calls work fine and the code is executed using this method in the C#:
[DllImport("myDLL.dll")]
public static extern void Function();
static void Main()
{
Function();
}
Now this works, I need the executing C++ code to send back the text to the C# where it can be displayed in a panel.
The text is "stage one..." executes code...then "stage two" etc, showing the processes running. Just basic stuff. I'm not sure how to approach this as I'm not a C++ guy. My main skills are .NET.
Cheers
Try using callbacks in C++ and sign them in C#
C++ part
typedef void (CALLBACK *pfNotifyMessage)(LPTSTR);
extern "C" AFX_API_EXPORT void SetNotifyMessage(pfNotifyMessageType pfNotify);
extern "C" AFX_API_EXPORT void Function();
In C++ Function call make call of pfNotifyMessage
C# part
public delegate void NotifyMessage(string message);
[DllImport("myDLL.dll")]
public static extern void SetNotifyMessage(NotifyMessage notify);
[DllImport("myDLL.dll")]
public static extern void Function();
in ะก# assign delegate with function