过去4个小时我一直试图解决一个非常神秘的问题.
我正在为记事本写一些插件.要实现语法高亮,必须导出这样的函数:
//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包装器函数,并且确实返回了一个函数指针.但是,任何调用该函数指针的尝试都会导致访问冲突.这意味着指针的类型错误或我当前缺少的其他东西.我已尝试使用void *,StdCall等.net导出函数的无数变体.所有这些都会导致同样的问题.
提前致谢!
解决方法
所以我终于设法找到了我的问题的解决方案.
static RTextLexerCliWrapper _lexerWrapper = new RTextLexerCliWrapper(); [DllExport(CallingConvention = CallingConvention.StdCall)] static IntPtr GetLexerFactory(uint index) { return (index == 0) ? _lexerWrapper.GetLexerFactory() : IntPtr.Zero; }
这种情况下的惯例必须是StdCall.否则堆栈指针无效,因此异常.
现在为了返回C实例的函数指针,事情有点棘手.
我静态存储CLI包装器类的实例,以便它不会得到GCed. (_lexerWrapper).
这个实例有一个名为GetLexerFactory的函数,它返回一个C实例的函数指针(然后由其他一些.dll用来获取某个对象的实际实例).
CLI Wrapper类如下所示:
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(); }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。