.net下com调用支持x86/x64
起因
项目涉及u3d/wpf端的渲染图形合成,采用了开源项目spout,为了便捷,采用了spout的com版本作为c#端的调用
项目调整后,细节已经捋清楚了。
但是考虑桌面应用采用anypc,根据运行环境自动切换x86/x64,就不想硬编码绑定运行环境了。
故选项后采用 程序选择anypc,运行时动态判断x86/x64,加载对应的com组件
封装代理层,代理层调用对应的x86/x64 com pinvoke
封装分析
项目 LightjamsSpout
我们需要封装的部分是
GLContext和LightjamsSpoutReceiver
都是com接口,硬编码直接实例化即可,动态调用时,不能实例化接口,需要通过反射拿到类型上面的特性 CoClassAttribute
通过获取 CoClassAttribute.CoClass 拿到实际类型去实例化
将x86/x64的库分别放在不同的路径,通过判断 IntPtr.Size == 4/!Environment.Is64BitProcess 判断是否是x86,反之则为x64
通过项目的引用,把com组件转换成 Interop.xx.dll ,路径为项目文件/obj/Debug,项目动态加载实际上是这个 Interop.xx.dll
代码实现
代理端动态加载Assmebly
loadDirectory = Path.Combine(Directory.GetCurrentDirectory(), IntPtr.Size == 4 ? "x86_Spout" : "x64_Spout");//LightjamsSpoutPS.dll
var loadFile = Path.Combine(loadDirectory, "Interop.LightjamsSpoutLib.dll");
assembly = Assembly.LoadFile(loadFile);
var type = assembly.GetType("LightjamsSpoutLib.LightjamsSpoutReceiver");
var coClassAttribute = type.GetCustomAttribute<CoClassAttribute>();
try
{
instance = Activator.CreateInstance(coClassAttribute.CoClass);
}
catch (Exception e)
{
RegisterCom(loadDirectory);
instance = Activator.CreateInstance(coClassAttribute.CoClass);
}
通过表达式树构建实例的方法
比如LightjamsSpoutReceiver.Connect
delegate string ConnectInvoke(string senderName, out int width, out int height);
private ConnectInvoke CreateConnect()
{
var senderNameParam = Expression.Parameter(typeof(string), "senderName");
var widthParam = Expression.Parameter(typeof(int).MakeByRefType(), "width");
var heightParm = Expression.Parameter(typeof(int).MakeByRefType(), "height");
var instanceExp = Expression.Constant(instance);
var method = instance.GetType().GetMethod("Connect");
var callExp = Expression.Call(instanceExp, method, new Expression[]{ senderNameParam, widthParam, heightParm });
return Expression.Lambda<ConnectInvoke>(callExp, new ParameterExpression[]{ senderNameParam, widthParam, heightParm }).Compile();
}
值得一提的是type.MakeByRefType是生成type对应的引用类型
毕竟定义是
public virtual string Connect(string senderName, out int width, out int height)
类型转换
有一个函数ReceiveImage,参数调用了com内部类型
public virtual void ReceiveImage(System.Array bytes, LightjamsSpoutLib.EPixelFormat format)
LightjamsSpoutLib.EPixelFormat是com内部的自定义枚举类型
根据内容,做一个枚举类型
public enum NePixelFormat
{
BGR,
RGB
}
表达式树的参数2改为int,内部转换 Expression.Convert 把 int 转换成对应的 LightjamsSpoutLib.EPixelFormat
调用函数的参数2改为NePixelFormat,内部调用委托时,转换成int即可
public void ReceiveImage(System.Array bytes, NePixelFormat format)
{
_receiveImage.Invoke(bytes, (int)format);
}
.net下com调用支持x86/x64的更多相关文章
- x86 x64下调用约定浅析
x86平台下调用约定 我们都知道x86平台下常用的有三种调用约定,__cdecl.__stdcall.__fastcall.我们分别对这三种调用约定进行分析. __cdecl __cdecl是C/C+ ...
- 使用CefSharp在C#访问网站,支持x86和x64
早已久仰CefSharp大名,今日才得以实践,我其实想用CefSharp来访问网站页面,然后抓取html源代码进行分析,如果使用自带的WebBrowser控件,可能会出现一些不兼容js的错误. Cef ...
- 关于.NET编译的目标平台(AnyCPU,x86,x64) (转)
关于.NET编译的目标平台(AnyCPU,x86,x64)(转) 今天有项目的代码收到客户的反馈,要求所有的EXE工程的目标平台全部指定成x86,而所有DLL工程的目标平台全部指定成AnyCPU . ...
- windows7内核分析之x86&x64第二章系统调用
windows7内核分析之x86&x64第二章系统调用 2.1内核与系统调用 上节讲到进入内核五种方式 其中一种就是 系统调用 syscall/sysenter或者int 2e(在 64 位环 ...
- X86/X64处理器体系结构及寻址模式
由8086/8088.x86.Pentium发展到core系列短短40多年间,处理器的时钟频率差点儿已接近极限.尽管如此,自从86年Intel推出386至今除了添加一些有关流媒体的指令如mmx/sse ...
- 关于VS项目平台的x86,x64,Any CPU以及Debug和Release的区别
相信对于很多刚接触打包程序的同志来说,关于x86,x64,Any CPU这三个项目平台,以及解决方案配置Debug和Release有什么区别?这个问题一定有许多的困惑,甚至不乏一些已经工作了很久的老程 ...
- 『开源重编译』System.Data.SQLite.dll 自适应 x86 x64 AnyCPU 重编译
背景: > System.Data.SQLite.dll 程序集 不能良好的支持 AngCPU 格式 System.Data.SQLite.dll 在 适应 x86 和 x64 有三个方案: & ...
- 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY
转载自: 数据库管理工具GUI - PremiumSoft Navicat Premium Enterprise 11.2.15 x86/x64 KEY Navicat Premium(数据库管理工具 ...
- QtCreator动态编译jsoncpp完美支持x86和arm平台
如果是做嵌入式开发. 在Qt下支持JSon最好的办法,可能不是采用qjson这个库.QJson这个库的实例只提供了x86环境下的编译方法. Installing QJson-------------- ...
随机推荐
- idea中快速将类中的属性转为Json字符串的插件
当我们想要测试接口的时候,难免会根据一个类,一个一个的写json数据,当属性比较少时还行,但当属性多的时候就比较麻烦了, 为了解决这个问题,我们可以安装第三方的插件来快速生成json字符串. 步骤如下 ...
- GAN和GAN的改进
GAN 原始GAN中判别器要最小化如下损失函数,尽可能把真实样本分为正例,生成样本分为负例: 其中是真实样本分布,是由生成器产生的样本分布. 第一个式子我们不看梯度符号的话即为判别器的损失函数,log ...
- java面试复习重点:类的管理及常用工具,教你抓住面试的重点!
java复习: 类的管理及常用工具类 包 写在程序文件的第一行 一个Java 源文件中只能声明一个包, 且声明语句只能作为源文件的第一条指令 导入类能导入非public类,但是不能用因为在其他包缺省的 ...
- 03_Service的绑定
Start Service启动的Service,Application退出,Service也不会退出: Bind Service启动的Service,Application退出,Service就会退出 ...
- jdk从1.8降到jdk1.7失败
1.将JAVA_HOME:的路径更改为1.7的相关路径,例如我的:C:\Java\jdk1.7.0_80 2.此时查看版本:Java -version,如果是1.8的版本,就把path路径下的%JAV ...
- ActiveMQ Cannot send, channel has already failed: tcp:127.0.0.1:8161
仅针对如下错误内容: Cannot send, channel has already failed: tcp://127.0.0.1:8161 一种尝试解决,修改连接端口为 61616: tcp:/ ...
- 老猿学5G:融合计费基于QoS流计费QBC的触发器Triggers
☞ ░ 前往老猿Python博文目录 ░ 一.引言 SMF中的功能体CTF在用户上网时达到一定条件就会向CHF上报流量,而CTF什么时候触发流量上报是由CTF中的触发器来控制的.在<老猿学5G: ...
- PyQt(Python+Qt)学习随笔:QListWidget获取指定项对应行的row方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QListWidget的row方法通过项作为参数,获取到对应项所在行的行号,语法如下: int ro ...
- PyQt(Python+Qt)学习随笔:部件的大小策略sizePolicy的含义
在Qt Designer中的每个部件,除了设置部件的位置(geometry)之外,还可以指定部件的大小策略sizePolicy.部件的sizePolicy用于说明部件在布局管理中的缩放方式,当部件没有 ...
- Python Flask后端异步处理(一)
Flask是Python中有名的轻量级同步Web框架,但是在实际的开发中,可能会遇到需要长时间处理的任务,此时就需要使用异步的方式来实现,让长时间任务在后台运行,先将本次请求的相应状态返回给前端,不让 ...