C++ function trigger C# function - c#

Basically my code is looks like below
Managed.dll
Managed.cs
class MyManagedClass
{
public ShowMessage()
{
System.out.println("My Message");
}
}
Wrapper.dll
ref class Wrapper
{
};
Native.lib
class NativeClass
{
public:
void NativeMessage()
{
cout<<"Print Message";
}
}
Main
void main
{
NativeClass ob;
ob.NativeMessage();
}
my issue is whenever the "ob.NativeMessage();" called, somehow MyManagedClass::ShowMessage() has to be triggered.
And more impotent Native.lib linked in Wrapper.dll and Wrapper.dll referenced in Managed.dll.
Can any one help me on this.

If you're running strictly from a C++ environment, you will want to host a .NET runtime in your C++ application. If you're running from a .NET environment, that part is already done and you will need to pass a delegate to the C++ code to be called later (this, by the way, is fraught with problems as the .NET runtime up to at least version 3.0 can and will garbage collect delegates out from under you).

Related

Call (C#) .NET Core method from C++

I have 2 components:
- .Net Core Application running on Ubuntu OS.
- C++ shared library (.so)
Now I want C++ component to be able to call .Net Core method, either passing interface to C++ component which will use this interface to callback method implementation or passing method as a parameter to C++ component.
High-level example what I am trying to achieve:
C# component :
public interface IDevice
{
void OnDataAvailable(string data);
}
public class Device: IDevice
{
[DllImport("sampleCPPLibrary.so")]
private static extern int SetReceiver(IDevice receiver);
public void OnDataAvailable(string data)
{
Console.WriteLine(data);
}
public void Initialize()
{
SetReceiver(IDevice(this))
}
}
C++ component:
extern "C" {
void SetReceiver(IReceiver * receiver)
{
receiver->OnDataAvailable(10);
}
}
Basically, what I am trying to do is just to pass some kind of "callback" to C++ component and call this "callback" when some event occurs in C++ component.
See See this issue from comments I constructed code where C# calls C and gives it callback delegate. Thus from C then it calls C#, and passes additional int type argument. See comments here from endurox project, and attached c-callback.tar.gz for working example.

C# code not catching SEHExceptions

I have a C# application that invokes a managed C++ DLL that deliberately accesses to an invalid address; I enabled SEH Exceptions in my C++ project, I added a _se_translator_function into my C++ code and I also added a signal handler when a SIGSEGV occurs. Using my C++ code from a purely native test, everything works perfectly, but when I invoke my C++ code from a .net app, the app crashes with a:
Unhandled Exception: System.AccessViolationException: Attempted to
read or write protected memory. This is often an indication that other
memory is corrupt.
at K.killnative() in c:\users\ebascon\documents\visual studio 2013\projects\consoleapplication3\consoleapplication4\source.cpp:line 32
This is my C# console app:
namespace ConsoleApplication3 {
class Program {
static void Main(string[] args) {
try {
var k = new NativeKiller();
k.kill();
}
catch (Exception ex) {
Console.WriteLine("Catching " + ex);
}
}
}
}
and this is the C++/CLI code invoked:
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*)
{
throw std::exception("Crash happens");
}
void killnative() {
try {
_set_se_translator(MXXExceptionTranslator);
signal(SIGSEGV, [](int) {
puts("Exception");
exit(-1);
});
int* p = reinterpret_cast<int*>(0xDEADBEEF);
printf("%d\n", *p);
}
catch (...) { //Removing this catch does not change anything
puts("Doing nothing");
}
}
public ref class NativeKiller {
public:
void kill() {
killnative();
}
};
What do you think I am doing wrong? In my real world problem, I need this C++/CLI process (that is a bridge with a legacy app) to log an error message and die gracefully instead of popping the "The program stopped working" window.
Thanks in advance,
Ernesto
This is the good kind of problem to have, it helps you discover that you are not building your code correctly. The C++/CLI compiler is pretty powerful, almost too powerful, and can translate almost any native code into IL. The exact same kind of IL that a C# compiler generates. And it is treated the same at runtime, the jitter translates it to machine code at runtime.
This is not usually something you actually want. Native C or C++ code ought to be translated directly to machine code by the compiler. The MSDN article for _set_se_translator() does a decent job of warning about this:
When using _set_se_translator from managed code (code compiled with /clr) or mixed native and managed code, be aware that the translator affects exceptions generated in native code only. Any managed exceptions generated in managed code (such as when raising System::Exception) are not routed through the translator function.
The usual way to fall in the pit of success is by compiling the native code separately in its own source file or library project. But even easier is to take advantage of the C++/CLI compiler's ability to dynamically switch back-and-forth between IL and machine code generation in a single source file. Fix:
#pragma managed(push, off)
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*) { ... }
void killnative() { ... }
#pragma managed(pop)
public ref class NativeKiller { ... }
And you'll now see that the exception translator works fine.

Cannot resolve/understand "overriding virtual function differs only by calling convention"

I currently had a pending question open - however after working on it I ran onto a new problem and the errors that I was getting while attempting to build it were:
Error 1 error C2695: 'MyEventsSink::OnSomethingHappened': overriding virtual function differs from 'Library::IEventsSink::OnSomethingHappened' only by calling convention
Error 2 error C2695: 'MyEventsSink::SomeTest': overriding virtual function differs from 'Library::IEventsSink::SomeTest' only by calling convention
I tried goggling regarding this error but I could not figure it out.
Here is what I am doing , I have a managed C# dll class library which is being consumed by a native C++ application. The code for C# interface is as follows and the implemention of this interface is in C++.
The C# code is
[ComVisible(true), ClassInterface(ClassInterfaceType.None), Guid("fdb9e334-fae4-4ff5-ab16-d874a910ec3c")]
public class IEventsSinkImpl : IEventsSink
{
public void OnSomethingHappened()
{
//Doesnt matter what goes on here - atleast for now
}
public void SomeTest(IEventsSink snk)
{
//When this is called - it will call the C++ code
snk.OnSomethingHappened();
}
}//end method
And its implemetation code in C++ is
class MyEventsSink : public Library::IEventsSink
{
public:
MyEventsSink() {}
~MyEventsSink() {}
virtual HRESULT OnSomethingHappened()
{
std::cout << "Incredible - it worked";
}
virtual HRESULT SomeTest(IEventsSink* snk)
{
//Doesnt matter this wont be called
}
};
Apparently during the build process VS2010 complains of the above mentioned errors. Any suggestions on how I could resolve those errors.
Try using __stdcall calling convention:
virtual HRESULT __stdcall OnSomethingHappened()
Normally, C++ uses the __cdecl calling convention, where the caller removes the parameters from the stack after the call. Most Windows API functions including COM use __stdcall where the callee removes the parameters from the stack.
Obviously, when you override a virtual function, the calling convention of both functions must be the same, because the function call is resolved at runtime.

C++/CLI wrapper for native C++ to use as reference in C#

Title explains. I have native C++ dlls that I'm writing C++/CLI wrappers for, which will in turn will be imported in C# as reference.
The problem is that in C# I don't see the classes I have in wrapper (imported from DLL).
What keywords should I use and HOW to re-declare my native C++ objects to become visible in C#?
Ok, tutorial. You have a C++ class NativeClass that you want to expose to C#.
class NativeClass {
public:
void Method();
};
1) Create a C++/CLI project. Link to your C++ library and headers.
2) Create a wrapper class that exposes the methods you want. Example:
#include "NativeClass.h"
public ref class NativeClassWrapper {
NativeClass* m_nativeClass;
public:
NativeClassWrapper() { m_nativeClass = new NativeClass(); }
~NativeClassWrapper() { this->!NativeClassWrapper(); }
!NativeClassWrapper() { delete m_nativeClass; }
void Method() {
m_nativeClass->Method();
}
};
3) Add a reference to your C++/CLI project in your C# project.
4) Use the wrapper type within a using statement:
using (var nativeObject = new NativeClassWrapper()) {
nativeObject.Method();
}
The using statement ensures Dispose() is called, which immediately runs the destructor and destroys the native object. You will otherwise have memory leaks and probably will die horribly (not you, the program). Note : The Dispose() method is magically created for you.

How to keep an object “persistent” in a C# dll?

I have written a dll in C#, offering a class for use. The dll is called by a C program that I have written. (It’s a plugin to some program. I have to write the plugin’s code in C, but I want to use the functionality of .NET, therefore the dll).
In the dll, I want to open up a stream and do other stuff that should be persistent between two calls to the dll. That is represented in the following code by the private member Connector.
namespace myCSharpDll
{
// the c++ program calls this methods
public interface IAccess
{
double Initialize();
double Timestep(double time, double[] values);
...
}
// E is the beginning of another program my dll should connect to, therefore the names
public class EAccess : IAccess
{
// EConnector is another class I defined in the same dll
private EConnector Connector;
public double InitializeE()
{
Connector = new EPConnector();
}
public double Timestep(double time, double[] values)
{
return Connector.Connect();
}
When I make a call to InitializeE() and later one to Timestep() the Connector oject points to NULL.
What do I have to do that when I call Timestep() from my C code, that I can access the before created instance of Connector?
I probably search in the wrong direction at all. Any tips are appreciated.
If I am not wrong you want to maintain a single object throughout the use of dll in c. If that is the case try something similar to singleton pattern.
http://en.wikipedia.org/wiki/Singleton_pattern
What singleton emphazises is you create only single object for a class and use it to perform all the work you need. Basically you might need a function that does something like this,
public class EAccess : IAccess
{
private static EConnector Connector
public EConnector getConnector(){
if(Connector == null){
Connector = new EConnector();
}
return Connector;
}
public double Timestep(double time, double[] values)
{
return getConnector().Connect();
}
};
Even though this is not the traditional way of doing things using singleton but I think it still does the work. I may be wrong. Please correct me if I have misunderstood something.
Thanks SLaks for asking for my C/C++ code. That is where the problem was located. It was simpler than I thought. I found the mistake while putting together the code to show you.
I know that C and C++ is not the same, the plugin structure is just a little weird. Most of the code was generated by a wizard. I just had to fill in my code. It's a cpp file, but the code seems to be C. Well, I think that is off topic.
Here it is, I extraced the most important lines.
// the dll is connected via COM, using the type library file that regasm generated
#import "[path]\myCSharpDll.tlb" raw_interfaces_only
using namespace myCSharpDll;
static void OnActivate (IfmDocument, Widget);
//off topic: this are the weird lines the wizard put in my way
#ifdef __cplusplus
extern "C"
#endif /* __cplusplus */
// when the plugin is called by the host program, this function is called
static void OnActivate (IfmDocument pDoc, Widget button)
{
InitializeIntermediate(pDoc);
Timestep1(...);
}
static void InitializeIntermediate(IfmDocument pDoc)
{
// Initialize COM.
HRESULT hr = CoInitialize(NULL);
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
double result = -1;
pIEPAccess->InitializeEP (&result);
...
}
static void Timestep1(...)
{
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
double result = -1.1;
pIEPAccess->Timestep (...);
...
// now I get a wrong result back here, because this call leads to nowhere as
// the connector object in the dll is void
}
I realized that I am requesting a second instance with that line
IEPAccessPtr pIEPAccess(__uuidof(EPAccess));
So I changed that pointer to one single instance and everything is fine. Thanks for your comments!

Categories

Resources