停滞在调用约定调用从非托管C ++的托管CLI方法 [英] Stuck on calling convention calling Managed CLI method from unmanaged C++

查看:192
本文介绍了停滞在调用约定调用从非托管C ++的托管CLI方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to call a managed method from unmanaged code. However, the managed code is requiring that I use the '(__clrcall) calling convention, and my unmanaged C++ code refuses to let me use the __clrcall calling convention without using the /clr option. I don't believe I want to do that as the unmanaged project is not mine to change to managed.

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

I have gone through constructing all those delegates and function pointer marshaling in the managed side as I have seen on CodeGuru and MSDN but this error still pops up unless I call a static function using a __stdcall convention that cannot be a member of a ref class. The method needs to be an instance of a ref class.

我已经能够解决这个问题的唯一方法是从汇编中的非托管代码执行我的方法调用在调用之后跳过ESP寄存器的弹出(添加4)(调用在参数中具有一个参数,因此为4)。这允许我有效地做一个__clrcall。这个选项臭了大时间。

The only way I have been able to get around this is to do my method call from the unmanaged code in assembly skipping the popping of the ESP register (adding 4) after the call (the call has one parameter in the argument thus the '4'). That allows me to effectively do a __clrcall. That option stinks big time.

任何人都有关于如何解决这个问题的任何想法?这肯定是可能的。我缺少一些简单但重要的信息。

Anybody have any ideas on how to work around this issue? It must surely be possible. I am missing some simple but vital piece of information.

这是我的委托定义(所有这些都属于单个ref类ManagedSensor):

Here is my delegate definition (all of these belong to a single ref class ManagedSensor):

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

这里是我想调用的实例方法

Here is the instance method I want to call

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

这里是ref类构造函数中的ref类函数与非托管函数的编组:

And here is the marshaling of the ref class function to the unmanaged function done in the ref class constructor:

    // 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()));

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

Hope somebody has a nice answer to this issue. I am probably missing something stupid.

推荐答案

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

That is supported. You can use an attribute to tell the CLR that the thunk it creates for the delegate should use the __cdecl calling convention. Make it look like this:

using namespace System::Runtime::InteropServices;

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

这篇关于停滞在调用约定调用从非托管C ++的托管CLI方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆