1

I have a C++ project containing a nonmanaged class method used to display string in a user interface :

void MyProject::displayIHM(std::string mystring);

This project is compiled with /clr because it calls another one made with C#/.NET 4.0. The goal of the .NET project is to make heavy computation tasks. During computation, we want to get back from it some information to the user interface.

My idea was to create two new methods in the C++-cli project :

void MyProject::displayFromDotNet(String^ mystring)
{
      displayIHM(ToStdString(mystring));
}

string ToStdString ( String ^ s)
{
   const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
   string os = chars;
   Marshal::FreeHGlobal(IntPtr((void*)chars));
   return os;
}

Until now, everything is ok but now the difficult part : how to provide displayFromDotNet to the .NET project. My idea was to provide a function pointer in the constructor of the .NET class and then to launch the process :

void (MyProject::*pointeurFunc)(String^) = &MyProject::displayFromDotNet;
ComputationProject^ kernel = gcnew ComputationProject((this->*pointeurFunc)); 
kernel->Compute();

The second line does not work. The constructor of ComputationProject has a IntPtr parameter but I do not know if I can convert a function pointer to an IntPtr^ in C++. I also made some attempts using Marshal::GetDelegateForFunctionPointer but it could not compile.

I do not know what to do, any help would be appreciated!

EDIT : yes ComputationProject is my C#/.NET project. The error with line 2 is "cannot convert parameter 1 from 'overloaded function type' to 'System::IntPtr'".

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
NicoGDF
  • 97
  • 12
  • You problem description could be clearer. I assume that ComputationProject is a C# class? When you say "The second line does not work" do you mean it is generating a compile error or a runtime error. I would expect a C/C++ function pointer to be more of a delegate in C#. Take a look at http://stackoverflow.com/questions/11425202/is-it-possible-to-call-a-c-function-from-c-net and http://stackoverflow.com/questions/6077329/how-do-i-call-a-c-function-from-c-sharp and see if that helps – Dweeberly Jul 31 '14 at 23:31
  • I edit my question. Unfortunately, your links do not help me. I cannot use a DLL import in my .NET project (ComputationProject) since I need to get the class method (and not a static method). I have to feed it using the constructor and gcnew but I do not know how to do this. – NicoGDF Aug 01 '14 at 08:18
  • You'll need to wrap the C++ instance function in a managed delegate – David Heffernan Aug 01 '14 at 08:26
  • Can you post the information that needs to be displayed as a message and have the C++ listen for your custom message? See [this question](http://stackoverflow.com/q/5083954/3581917) for how to send message from c#. – Evil Dog Pie Aug 01 '14 at 08:39
  • David : how can I do this ? Mike : it looks like to me very complicated for only transmitting string messages to the IHM – NicoGDF Aug 01 '14 at 09:04
  • You read the documentation on MSDN that covers the topic of delegates for C++/CLI. Or perhaps you don't know what a delegate is. – David Heffernan Aug 01 '14 at 09:06

1 Answers1

-1

I finally find a (ugly) way.

My main problem was I could not pass a method pointer to C# because it is not a real function pointer (so I cannot cast it to IntPtr). I decided to create a second class containing a static MyProject object and a static method calling displayIHM on the static object :

class StaticMyProject
{
public :
    static MyProject staticObject;
    static void DisplayInIHM(char *);
}; 

In cpp :

MyProject StaticMyProject::objetStatique;

void StaticMyProject::DisplayInIHM(char *message)
{
    std::string message2(message);
    staticObject.displayIHM(message2);
}

Now for calling Compute method of ComputationProject, I modified the code like this :

StaticMyProject::objetStatique = *this;
void (*funcPointer)(char*) = StaticMyProject::DisplayInIHM;
ComputationProject^ kernel = gcnew ComputationProject((IntPtr)funcPointer);
kernel->Compute();

And in my ComputationProject.cs :

public class ComputationProject
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void FunctionPointer([MarshalAs(UnmanagedType.LPStr)]string message);

        public readonly FunctionPointer DisplayMethod;

        public ComputationProject(IntPtr ptr)
        {
            this.DisplayMethod = (FunctionPointer)Marshal.GetDelegateForFunctionPointer(ptr, typeof(FunctionPointer));                       
        }

        public int Compute()
        {            
            this.DisplayMethod("Beginning computation...");
            ...
        }
    }
NicoGDF
  • 97
  • 12
  • You need a managed class to implement the delegate. It does that by calling the unmanaged instance function. – David Heffernan Aug 01 '14 at 11:58
  • See my precedent comment... I do not know how to use a delegate in this case. It would be far greater than my previous solution but I do not know how to do. – NicoGDF Aug 01 '14 at 12:08
  • There is plenty of documentation of delegates. Have you read it? – David Heffernan Aug 01 '14 at 12:09
  • I found some samples like here [link](http://www.visualcplusdotnet.com/visualcplusdotnet20c.html) but I cannot adapt them to my problem. – NicoGDF Aug 01 '14 at 12:12