首页 / C# / c# – 导出非托管函数指针时访问冲突
c# – 导出非托管函数指针时访问冲突
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 导出非托管函数指针时访问冲突,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3005字,纯文字阅读大概需要5分钟。
内容图文
过去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导出函数的无数变体.所有这些都会导致同样的问题.
有没有其他方法可以返回C类的函数指针?或者我做错了什么?
提前致谢!
解决方法:
所以我终于设法找到了我的问题的解决方案.
第一步是使用正确的调用约定导出函数:
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();
}
所以,我们在这里管理的是,通过.NET导出一个能够返回纯C对象的函数指针.
内容总结
以上是互联网集市为您收集整理的c# – 导出非托管函数指针时访问冲突全部内容,希望文章能够帮你解决c# – 导出非托管函数指针时访问冲突所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。