2

我正在尝试从非托管代码调用托管方法。但是,托管代码要求我使用 '(__clrcall) 调用约定,而我的非托管 C++ 代码拒绝让我在不使用 /clr 选项的情况下使用 __clrcall 调用约定。我不相信我想这样做,因为非托管项目不是我要更改为托管的。

正如我在 CodeGuru 和 MSDN 上看到的那样,我已经在托管端构建了所有这些委托和函数指针封送处理,但除非我使用不能成为 ref 类成员的 __stdcall 约定调用静态函数,否则此错误仍然会弹出。该方法需要是 ref 类的实例。

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

有人对如何解决此问题有任何想法吗?这肯定是可能的。我错过了一些简单但重要的信息。

这是我的委托定义(所有这些都属于单个 ref 类 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()));

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

4

1 回答 1

7

这是支持的。您可以使用属性告诉 CLR 它为委托创建的 thunk 应该使用 __cdecl 调用约定。让它看起来像这样:

using namespace System::Runtime::InteropServices;

[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
delegate void OxpOnReceivedMeasurement(std::vector<OBX> *obxes);
于 2013-04-28T17:35:50.707 回答