整体描述:
ATL做的COM组件,C#做的界面。
C#调用COM组件进行业务处理,C++需要回调到C#界面。
基本打通了,回调参数如果是普通参数的话,如LONG*的话,没问题
但如果是结构的话,
hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, NULL);
这句话会返回失败:有一个参数无效
IDL:
struct Point
{
LONG x, y;
};
struct PROPERTY
{
struct Point pt;
FLOAT x;
FLOAT y;
FLOAT z;
FLOAT f;
};
dispinterface IEvents
{
methods:
[id(1)] HRESULT GetProperty([in] int index, [in, out] struct PROPERTY* prop);
};
考虑到结构后面一定会经常变化或扩充,所以不希望把参数展开一个个用指针来写回调 :)
类似的问题别人也早问了,没得到解决方法:
http://bbs.csdn.net/topics/390592325
11 个解决方案
#1
C#不熟,纯属个人意见
struct _tagMySruct_t
{
int cbSize;
LONG ……
}MYSTRUCT, *LPSTRUCT;
传递一个 void *指针, 然后强制转换
struct _tagMySruct_t
{
int cbSize;
LONG ……
}MYSTRUCT, *LPSTRUCT;
传递一个 void *指针, 然后强制转换
#2
我在IDL里定义了结构,这样C#与C++结构容易互通。
否则c#还要自己定义结构,描述比C++复杂。
#3
不要做A语言代码修改为B语言代码的无用功。
也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。
只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。
即可很方便地让A、B两种语言之间协调工作。
比如:
A将请求数据写到文件a.txt,写完后改名为aa.txt
B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
A发现bb.txt存在时,读取其内容,读完后删除bb.txt
以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。
除非A或B不支持判断文件是否存在、文件读写和文件更名。
但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
可以将临时文件放在RamDisk上提高效率减少磨损磁盘。
数据的结构很复杂的话,文本文件的格式问题可参考json或xml
共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的:
·进程之间松耦合
·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。
·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。
·方便在线开关服务,只需删除或创建该临时文本文件即可。
·方便实现分布式和负载均衡。
·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满)
·……
“跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边,
回头是“使用共享纯文本文件进行信息交流”的岸!
也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。
只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。
即可很方便地让A、B两种语言之间协调工作。
比如:
A将请求数据写到文件a.txt,写完后改名为aa.txt
B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
A发现bb.txt存在时,读取其内容,读完后删除bb.txt
以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。
除非A或B不支持判断文件是否存在、文件读写和文件更名。
但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
可以将临时文件放在RamDisk上提高效率减少磨损磁盘。
数据的结构很复杂的话,文本文件的格式问题可参考json或xml
共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的:
·进程之间松耦合
·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。
·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。
·方便在线开关服务,只需删除或创建该临时文本文件即可。
·方便实现分布式和负载均衡。
·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满)
·……
“跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边,
回头是“使用共享纯文本文件进行信息交流”的岸!
#4
你的说法让人很无语,真的
1.COM是很标准的规范,应用也很广泛,它本身就支持跨语言,现在碰到一点难点就放弃,不是开发者风格
2.你觉得文件读写是可以满足一般的要求,但是如果是对高实时性、数据量较大的需求,文本读写并不合适
3.实现文本通信,还搞出内存文件了,开发效率并不高,对后期长远来看,我觉得不是最好的选择。
#5
不用结构体,用SAFEARRAY传递数组的方式
#6
COM支持跨语言?
能跨
Apple ][
C51
DOS
Linux
Android
iOS
VxWorks
Arduino
……
吗?
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
能跨
Apple ][
C51
DOS
Linux
Android
iOS
VxWorks
Arduino
……
吗?
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
#7
那C#那端也按数组访问了呗,就是可读性会很差,随着结构越来越复杂。
看网上还有转成BSTR,不知道是说用BSTR当内存块传数据(BSTR本身有大小),还是转成真正的字符串描述:format?
我用网上的其他人的方法,把整个结果序列化进VT结构,都是返回出错,不知道是COM服务端自身处理参数时出错,还是客户端C#在转换成C#可用的数据时出错。。。
#8
我用C#调用COM的GetXXX或SetXXX类方法,使用结构是没问题的,证明了COM在处理结构参数是能搞定的。
就是到了回调部分结构有问题。
不知道是不会用,还是MS实现上没做好。。。
#9
顶顶顶顶顶顶顶顶
#10
结构体改为一个独立的COM对象就解决了,返回的是COM对象接口指针的变体值,然后C#把该COM对象接口变体指针强制转换为实际的COM对象类型指针
#11
这样感觉写代码就比较复杂了
c#调用我C++写的com,结构传进传出,都很正常,证明各种参数序列化是正常的,为啥到连接点就不行了,奇怪。
#1
C#不熟,纯属个人意见
struct _tagMySruct_t
{
int cbSize;
LONG ……
}MYSTRUCT, *LPSTRUCT;
传递一个 void *指针, 然后强制转换
struct _tagMySruct_t
{
int cbSize;
LONG ……
}MYSTRUCT, *LPSTRUCT;
传递一个 void *指针, 然后强制转换
#2
我在IDL里定义了结构,这样C#与C++结构容易互通。
否则c#还要自己定义结构,描述比C++复杂。
#3
不要做A语言代码修改为B语言代码的无用功。
也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。
只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。
即可很方便地让A、B两种语言之间协调工作。
比如:
A将请求数据写到文件a.txt,写完后改名为aa.txt
B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
A发现bb.txt存在时,读取其内容,读完后删除bb.txt
以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。
除非A或B不支持判断文件是否存在、文件读写和文件更名。
但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
可以将临时文件放在RamDisk上提高效率减少磨损磁盘。
数据的结构很复杂的话,文本文件的格式问题可参考json或xml
共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的:
·进程之间松耦合
·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。
·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。
·方便在线开关服务,只需删除或创建该临时文本文件即可。
·方便实现分布式和负载均衡。
·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满)
·……
“跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边,
回头是“使用共享纯文本文件进行信息交流”的岸!
也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。
只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。
即可很方便地让A、B两种语言之间协调工作。
比如:
A将请求数据写到文件a.txt,写完后改名为aa.txt
B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt
A发现bb.txt存在时,读取其内容,读完后删除bb.txt
以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。
除非A或B不支持判断文件是否存在、文件读写和文件更名。
但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
可以将临时文件放在RamDisk上提高效率减少磨损磁盘。
数据的结构很复杂的话,文本文件的格式问题可参考json或xml
共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的:
·进程之间松耦合
·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。
·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。
·方便在线开关服务,只需删除或创建该临时文本文件即可。
·方便实现分布式和负载均衡。
·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满)
·……
“跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边,
回头是“使用共享纯文本文件进行信息交流”的岸!
#4
你的说法让人很无语,真的
1.COM是很标准的规范,应用也很广泛,它本身就支持跨语言,现在碰到一点难点就放弃,不是开发者风格
2.你觉得文件读写是可以满足一般的要求,但是如果是对高实时性、数据量较大的需求,文本读写并不合适
3.实现文本通信,还搞出内存文件了,开发效率并不高,对后期长远来看,我觉得不是最好的选择。
#5
不用结构体,用SAFEARRAY传递数组的方式
#6
COM支持跨语言?
能跨
Apple ][
C51
DOS
Linux
Android
iOS
VxWorks
Arduino
……
吗?
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
能跨
Apple ][
C51
DOS
Linux
Android
iOS
VxWorks
Arduino
……
吗?
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
#7
那C#那端也按数组访问了呗,就是可读性会很差,随着结构越来越复杂。
看网上还有转成BSTR,不知道是说用BSTR当内存块传数据(BSTR本身有大小),还是转成真正的字符串描述:format?
我用网上的其他人的方法,把整个结果序列化进VT结构,都是返回出错,不知道是COM服务端自身处理参数时出错,还是客户端C#在转换成C#可用的数据时出错。。。
#8
我用C#调用COM的GetXXX或SetXXX类方法,使用结构是没问题的,证明了COM在处理结构参数是能搞定的。
就是到了回调部分结构有问题。
不知道是不会用,还是MS实现上没做好。。。
#9
顶顶顶顶顶顶顶顶
#10
结构体改为一个独立的COM对象就解决了,返回的是COM对象接口指针的变体值,然后C#把该COM对象接口变体指针强制转换为实际的COM对象类型指针
#11
这样感觉写代码就比较复杂了
c#调用我C++写的com,结构传进传出,都很正常,证明各种参数序列化是正常的,为啥到连接点就不行了,奇怪。