Return string from c++ function pointer invoked from c# - c++-cli

I need to call a c++ callback function from c# that returns a String. When I try with the code below the application crashes hard (with a message saying that it may be due to a corruption of the heap).
Here's the c++ code:
static String^ CppFunctionThatReturnsString()
{
return gcnew String("From C++");
}
void main()
{
CSharp::CSharpFunction(IntPtr(CppFunctionThatReturnsString));
}
And here's the c# code:
public class CSharp
{
private delegate string CppFuncDelegate();
public static void CSharpFunction(IntPtr cppFunc)
{
var func = (CppFuncDelegate)Marshal.GetDelegateForFunctionPointer(cppFunc, typeof(CppFuncDelegate));
func(); // Crash
}
}
Do I have to do some kind of marshaling magic with the string before returning it?

Why are you using function pointers in the first place? Just pass an instance of the delegate to the C# code:
C++:
static String^ CppFunctionThatReturnsString()
{
return gcnew String("From C++");
}
void main()
{
CSharp::CSharpFunction(new CSharp::CppFuncDelegate(CppFuncThatReturnsString));
}
C#:
public class CSharp
{
private delegate string CppFuncDelegate();
public static void CSharpFunction(CppFuncDelegate d)
{
d();
}
}
I think you may need to put CppFuncThatReturnsString inside a class.

I found the answer on this ten year old page.
c++:
static const char* __stdcall CppFunctionThatReturnsString()
{
return "From C++";
}
void main()
{
CSharp::CSharpFunction(IntPtr(CppFunctionThatReturnsString));
}
c#:
public class CSharp
{
private delegate IntPtr CppFuncDelegate();
public static void CSharpFunction(IntPtr cppFunc)
{
var func = (CppFuncDelegate)Marshal.GetDelegateForFunctionPointer(cppFunc, typeof(CppFuncDelegate));
Marshal.PtrToStringAnsi(func());
}
}
That is, pass it as an IntPtr and marshal it into a string on the C# side.

Related

Using HangFire to call action delegate produces exception

I'm trying to use HangFire to call an action method on a class. From the code below, the action method works correctly if called outside of HangFire, but throws an exception when using HangFire. I also tried using Invoke() as stated by other similar posts.
Expression body should be of type
'MethodCallExpression'(Parameter'methodCall')'
I'd like to figure out how to have HangFire execute this type of method if possible.
class Program
{
static void Main(string[] args)
{
var a = new ActionTest();
// Calling this method prints out Hello World correctly
a.DoAction();
GlobalConfiguration.Configuration.UseSqlServerStorage(#"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Test;Integrated Security=True");
// Call this method from HangFire produces exception: Expression body should be of type 'MethodCallExpression'(Parameter'methodCall')'
BackgroundJob.Enqueue<ActionTest>(a => a.DoAction());
}
}
public class ActionTest
{
public ActionTest()
{
DoAction = WriteHello;
}
public Action DoAction;
public void WriteHello()
{
Console.WriteLine("Hello World");
}
}
I don't see any other way than wrapping the call to DoAction in a genuine method :
public class ActionTest
{
public ActionTest()
{
DoAction = WriteHello;
}
public Action DoAction;
public void InvokeAction()
{
DoAction();
}
public void WriteHello()
{
Console.WriteLine("Hello World");
}
}
then
BackgroundJob.Enqueue<ActionTest>(a => a.InvokeAction());

reference variables and objects

I wanted to know why this did not work, as in why didn't the compiler invoke the restart method within the computer class...
Consider the following scenario:
I have 3 classes as shown below:
public class Computer {
public int compStatus = 0; //0 means off, 1 means on.
public void turnOn(){
this.compStatus = 1;
}
public void turnOff(){
this.compStatus = 0;
}
public void restart(){
if(compStatus ==1){
System.out.println("Turning off");
compStatus = 0;
System.out.println("Turning on");
compStatus = 1;
System.out.println("Restart successful");
}
}
}
Now the sub-class:
public class Macintosh extends Computer {
public void openXCode(){
if(compStatus == 1){
System.out.println("XCode Compiler opened.");
}
else{
System.out.println("Mac is off.");
}
}
public void restart(){
System.out.println("Mac restarted");
}
}
The tester class:
public class CompTest {
public static void main(String[] args){
Computer testObj = new Macintosh();
testObj.turnOn();
testObj.restart(); ///ERROR HERE
}
}
I am aware that the compiler checks if the restart method is in the class of the reference variable 'Computer' not the class of the actual object at the other end of the reference 'macintosh'. So if what I have said is true, why is the restart method not invoked?
You have to call the base class method in order to actually restart. Your method is just hiding the base method. You should override the method and then call it base.restart to do what you want.

MethodDecorator.Fody and getting parameter values

I was wondering if with MethodDecorator it's possible to have the passed parameter during the OnException... that would be great since if I can catch an exception I can also have the passed parameter values
Consider this piece of code
static void Main(string[] args)
{
Worker worker = new Worker();
worker.DoWork(6);
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Assembly | AttributeTargets.Module)]
public class LoggableAttribute : Attribute, IMethodDecorator
{
public void OnEntry(System.Reflection.MethodBase method)
{
var args = method.GetParameters();
var arguments = method.GetGenericArguments();
}
public void OnExit(System.Reflection.MethodBase method)
{
}
public void OnException(System.Reflection.MethodBase method, Exception exception)
{
}
}
and
public class Worker
{
[Loggable]
public void DoWork(int i )
{
}
}
I wish to have 6 on the OnEntry/Nor OnException
Thanks
I know this is an old question, but in case someone stumbles upon this like I did, you can add an Init method and capture the argument values there.
e.g:
public class LoggableAttribute : Attribute, IMethodDecorator
{
private object[] arguments;
public void Init(object instance, MethodBase method, object[] args) {
this.arguments = args;
}
public void OnEntry()
{
// this.arguments[0] would be 6 when calling worker.DoWork(6);
}
}
Check out the example on https://github.com/Fody/MethodDecorator

Working example of a Singleton

In C#, I want to implement Singletons to provide data in one thread to many other threads.
I have decided to use this lazy form of Singleton from Jon Skeet (thanks, Jon!):
public sealed class Singleton
{
Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly Singleton instance = new Singleton();
}
}
So far, so good. ... but how does one use that?
What I want to do is share a single instance of the following data:
public bool myboolean = false ;
public double mydoubles[] = new double[128,3] ;
public IntPtr myhandles[] = new IntPtr[128] ;
How do I declare and reference these data as Singletons?
I also need them to be referenceable across different namespaces.
Many thanks!
// thread-safety
public sealed class Singleton
{
private static Singleton instance = null;
private static readonly object padlock = new object();
private bool myboolean = false;
private double[,] mydoubles = new double[128, 3];
private IntPtr[] myhandles = new IntPtr[128];
Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
}
and to access
//Singleton.Instance.myboolean
//Singleton.Instance.mydoubles
//Singleton.Instance.myhandles

how to check the an interface type in c++/cli

i want to convert that line from c# to c++/cli
Idocobj is IPart
IPart is an interface and Idocobj is an object.Are there any way to do this conversion.
i used this code :
Idocobj->GetType() == IPart::typeid
but it dosen't work
You can use dynamic_cast to check for "is". Here is an example:
using namespace System;
namespace NS
{
public interface class IFoo
{
void Test();
};
public ref class Foo : public IFoo
{
public: virtual void Test() {}
};
public ref class Bar
{
public: virtual void Test() {}
};
}
template<class T, class U>
bool isinst(U u) {
return dynamic_cast< T >(u) != nullptr;
}
int main()
{
NS::Foo^ f = gcnew NS::Foo();
NS::Bar^ b = gcnew NS::Bar();
if (isinst<NS::IFoo^>(f))
Console::WriteLine("f is IFoo");
if (isinst<NS::IFoo^>(b) == false)
Console::WriteLine("f is not IFoo");
Console::ReadKey();
}
But normally, you never use "is".... you always want to do something with the check... so normally you should use "as" which directly mapps to dynamic_cast:
NS::IFoo^ ifoo = dynamic_cast<NS::IFoo^>(f);
if (ifoo != nullptr)
{
// Do something...
ifoo->Test();
}