2013-04-28 195 views
2

我想从非托管代码调用托管方法。但是,托管代码要求我使用'(__clrcall)调用约定,而我的非托管C++代码拒绝让我使用__clrcall调用约定而不使用/ clr选项。我不相信我想这样做,因为非托管项目不是我的需要改变为托管。卡住调用从非托管C++调用托管CLI方法

我已经通过在CodeGuru和MSDN上看到的构造了托管端的所有这些委托和函数指针封送,但是这个错误仍然会弹出,除非我使用__stdcall约定不能成为静态函数一个ref类。该方法需要是ref类的一个实例。

我已经能够解决这个问题的唯一方法是从程序集中的非托管代码执行我的方法调用,在调用之后跳过ESP寄存器的弹出(添加4)(该调用在参数中有一个参数因此'4')。这可以让我有效地做一个__clrcall。这个选项让人感到很难过。

任何人有关于如何解决此问题的任何想法?它一定是可能的。我错过了一些简单而重要的信息。

这里是我的委托定义(所有这些属于一个引用类ManagedSensor):

 delegate void OxpOnReceivedMeasurement(std::vector<OBX> *obxes); 

这里是实例方法我想打电话给

 void LocalOxpMeasurementCallback(std::vector<OBX> *obxes); 

这里是封送处理的ref类函数在ref类构造函数中完成的非托管函数:

// Now to make the 'delegate' unmanaged function pointer usable for unmanged code 
    // The argument is the unmanaged callback. 
    OxpOnReceivedMeasurement ^oxpMeasurementCallbackFP = gcnew OxpOnReceivedMeasurement(this, &ManagedSensor::LocalOxpMeasurementCallback); 
    // Lock it so the garbage collector doesnt get rid of it or move it 
    gch = GCHandle::Alloc(oxpMeasurementCallbackFP); 
    // Pass the marshaled function pointer to the unmanaged code 
    IntPtr ip = Marshal::GetFunctionPointerForDelegate(oxpMeasurementCallbackFP); 
    // fnOnReceiveMeasurement is defined in OxpLibTransports.h which matches the delegate 
    // this passes the function pointer to the unmanaged Sensor class to be used when a 
    // measurement is received 
    _sensor->RegisterForMeasurementCallback((fnOnReceiveMeasurement)(ip.ToPointer())); 

希望有人对此问题有一个很好的答案。我可能错过了一些愚蠢的东西。

回答

6

支持。你可以使用一个属性告诉CLR它为它创建的thunk应该使用__cdecl调用约定。使它看起来像这样:

using namespace System::Runtime::InteropServices; 

[UnmanagedFunctionPointer(CallingConvention::Cdecl)] 
delegate void OxpOnReceivedMeasurement(std::vector<OBX> *obxes); 
+0

再次感谢!两次不到24小时。这比在线装配好得多,可以消除单个添加esp,4声明。非常感激。 – 2013-04-28 20:38:15