在过去的4个小时中,我一直在尝试解决一个非常神秘的问题。

我正在为Notepad ++写一些插件。 要实现语法高亮显示,必须导出此类功能:

//this function is exported via exports.def file
LexerFactoryFunction SCI_METHOD GetLexerFactory(unsigned int index)
{
    return (index == 0) ? RTextLexer::LexerFactory : nullptr;
}

哪里,

LexerFactoryFunction is typedef ILexer *(*LexerFactoryFunction)();
#define SCI_METHOD __stdcall

我设法使该东西与C ++完美配合,但是该插件的另一部分是用C#编写的,所以我尝试使用Fody Costura NuGet软件包将两者合并(以便将CLI .dll嵌入到主.dll中)。 ,但是没有成功。

我尝试过的

public ref class RTextLexerCliWrapper
{
public:
    delegate ILexer * GetLexerFactoryDelegate();

IntPtr GetLexerFactory()
{
    return System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(_lexerFactoryPtr);
}

RTextLexerCliWrapper();
private:
    GetLexerFactoryDelegate ^ _lexerFactoryPtr;
    GCHandle gch;

    ~RTextLexerCliWrapper();
};

RTextLexerCliWrapper::RTextLexerCliWrapper()
{
    _lexerFactoryPtr = gcnew GetLexerFactoryDelegate(&RTextLexer::LexerFactory);
    gch = GCHandle::Alloc(_lexerFactoryPtr);
}


RTextLexerCliWrapper::~RTextLexerCliWrapper()
{
    gch.Free();
}

此CLI包装器在我的主.dll中像这样引用:

static RTextLexerCliWrapper _lexerWrapper = new RTextLexerCliWrapper();

[DllExport(CallingConvention = CallingConvention.Cdecl)]
static IntPtr GetLexerFactory(uint index)
{            
     return (index == 0) ? _lexerWrapper.GetLexerFactory() : IntPtr.Zero;
}

因此发生的是,确实调用了我的.net函数,还调用了cli wrapper函数,并且确实返回了函数指针。 但是,任何尝试调用该函数指针的操作都会导致访问冲突。 这意味着指针类型错误或我当前缺少的其他东西。 我尝试了无数.net导出函数的变体,它们带有void *, StdCall等。所有这些都导致相同的问题。

还有其他方法可以返回C ++类的函数指针吗? 还是我做错了什么?

提前致谢!

#1楼 票数:1 已采纳

因此,我终于设法找到了解决我问题的方法。

第一步是使用正确的调用约定导出函数:

    static RTextLexerCliWrapper _lexerWrapper = new RTextLexerCliWrapper();

    [DllExport(CallingConvention = CallingConvention.StdCall)]
    static IntPtr GetLexerFactory(uint index)
    {            
        return (index == 0) ? _lexerWrapper.GetLexerFactory() : IntPtr.Zero;
    }

在这种情况下,约定必须为StdCall。 否则,堆栈指针将无效,因此是异常。

现在,为了返回C ++实例的函数指针,事情有些棘手。

我静态地存储了CLI包装类的实例,以便不会被GC。 _lexerWrapper )。

该实例具有一个称为GetLexerFactory的函数,该函数返回C ++实例的函数指针(然后,其他.dll使用该指针来获取某个对象的实际实例)。

CLI包装器类如下所示:

    public ref class RTextLexerCliWrapper
    {
    public:

        delegate ILexer * GetLexerFactoryDelegate();

        IntPtr GetLexerFactory()
        {
            return System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(_lexerFactoryPtr);
        }

        RTextLexerCliWrapper();

    private:
        GetLexerFactoryDelegate ^ _lexerFactoryPtr;
        GCHandle gch;

        ~RTextLexerCliWrapper();
    };

ILexer *是对象的类型,我们稍后将返回它。

    RTextLexerCliWrapper::RTextLexerCliWrapper()
    {
        _lexerFactoryPtr = gcnew GetLexerFactoryDelegate(&RTextLexer::LexerFactory);
        gch = GCHandle::Alloc(_lexerFactoryPtr);
    }


    RTextLexerCliWrapper::~RTextLexerCliWrapper()
    {
        gch.Free();
    }

因此,我们在这里管理的是通过.NET导出能够返回纯C ++对象的函数指针。

  ask by FailedDev translate from so

未解决问题?本站智能推荐:

1回复

当用作c/CLI中函数的参数(托管)时,等效于c/CLI中的ac#类

我有一个ac#文件,如下所示: 我使用包含头文件的c ++ / CLI包装器dll对其进行包装,如下所示: ** MyImageHandler是一个托管类。所以我要通过__stdcall导出它。我这样做正确吗? **现在,我有一个实现上述头文件的头文件,然后是一个cpp文件,如下所示:
1回复

从非托管C++代码调用C#函数时无法处理异常

问题的想法如下:我将 C# 函数指针传递给 C++ 编译库,然后从 C++ 调用传递的函数。 我想从代码中捕获 C#/C++ 异常,它位于 C++ 函数调用之前。 问题的想法如下:我将 C# 函数指针传递给 C++ 编译库,然后从 C++ 调用传递的函数。 我的 C++ 调用包含在try/catch
1回复

将私有成员指针传递给非托管函数C++/CLI

我在将非托管指针(作为成员存储在托管包装器中)传递给需要双指针(指向存储的非托管指针的指针)的非托管函数时遇到了麻烦。 此问题说明如下: 我为下面声明的非托管C结构提供了一个包装器: 我需要从C Dll调用一个函数: 目标是更改myObj-> RTO指向的数据...不幸的是,
1回复

导出托管的C#函数以将更改的char*参数返回到非托管代码

我有一个本地C ++(我认为)应用程序,可以将其配置为加载某个dll并调用一个函数。 此函数返回int,接受四个参数,应更改两个参数中的至少一个并返回一个值。 根据手册,此功能应在C ++中定义为: 但是,根据需要,此功能应在C#中实现。 我正在使用“不受管理的导出”来允许我使用:
1回复

从C#调用非托管C++

我在Win4上使用.NET 4.0运行VS2012。 我尝试过以下方法: 创建C ++ DLL项目 选中\\取消选中导出符号框 我确保我的平台目标是一样的。 在我的情况下,win32 我已经在需要的地方添加了必要的extern“C”和__declspec(dllexp
1回复

托管类和非托管类之间的继承

您好,我对混合C ++和C#的项目中的继承有疑问。 所以我有一个C ++ / CLI层在两者之间做事。 在C ++中,我有2种结构: 然后在C ++ / CLI中,我在其托管版本中有2个相同的类。 每个人都有一个指向非托管C ++类的指针。 版本1: 版本2: 问题 :
1回复

如何在C#中读取(本机)DLL的导出函数名称?

我知道我可以读取PE规范以编写执行此操作的代码。 但是,由于我手上没有很多时间,所以我希望你们中的一些人可能已经准备好了这样的代码样本。 重要提示: 32位和64位之间有什么区别吗? 感谢您的时间!
1回复

引用类中的指针到成员函数

我正在尝试使用自定义.NET ref类来控制按钮系统。 它由添加到父窗体中的类内的PictureBox组成。 当检测到单击时,它需要调用在构造函数中指定的函数,该函数是父类内部的方法。 例如: 当我按照说明进行操作时,以上内容会导致“使用&ns :: form :: cp创建指向成员