将本机指针函数传递给C#方法

时间:2014-07-31 22:54:09

标签: c# c++-cli clr function-pointers

我有一个C ++项目,其中包含一个非托管类方法,用于在用户界面中显示字符串:

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

这个项目是用/ clr编译的,因为它调用另一个用C#/ .NET 4.0编写的项目。 .NET项目的目标是进行繁重的计算任务。在计算过程中,我们希望从中获取一些信息到用户界面。

我的想法是在C ++中创建两个新方法 - cli项目:

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;
}

到目前为止,一切正常,但现在是困难的部分:如何将displayFromDotNet提供给.NET项目。我的想法是在.NET类的构造函数中提供一个函数指针,然后启动该进程:

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

第二行不起作用。 ComputationProject的构造函数有一个IntPtr参数,但我不知道我是否可以在C ++中将函数指针转换为IntPtr ^。我也尝试使用Marshal :: GetDelegateForFunctionPointer,但无法编译。

我不知道该怎么做,任何帮助都会受到赞赏!

编辑:是的ComputationProject是我的C#/ .NET项目。第2行的错误是“无法将参数1从'重载函数类型'转换为'System :: IntPtr'”。

1 个答案:

答案 0 :(得分:-1)

我终于找到了一种(丑陋的)方式。

我的主要问题是我无法将方法指针传递给C#,因为它不是真正的函数指针(因此我无法将其转换为IntPtr)。 我决定创建一个包含静态MyProject对象的第二个类和一个在静态对象上调用displayIHM的静态方法:

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

在cpp:

MyProject StaticMyProject::objetStatique;

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

现在,为了调用ComputationProject的Compute方法,我修改了这样的代码:

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

在我的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...");
            ...
        }
    }