64位程序调用32位DLL

        近期再把原来写的股票分析程序转换成64位版本号,程序中调用了银江的通视数据接口dll,由于银江提供的dll是32位的,但windows以下64位程序并不能直接调用32位的dll,所以仅仅能百度了.
        网上有说用进程外com的方式能够,之前从没接触过com,硬着头皮搞了半天,发现了问题,进程外com对于dll提供函数返回值不涉及指针的话没有不论什么问题,可是假设dll函数返回值是一个指针,问题就来了,因为这个指针和我自己的数据接收程序不在同一个进程地址空间,所以根本没有办法通过指针得到正确的接收数据.所以仅仅能放弃这种方法,转向怎样在进程间传递数据.
        我自己程序是用QT编写,mingw编译的,网上关于进程间通信(IPC)资料一大把,看了一下基本上QT在windows以下假设想在进程间传递大数据,仅仅能用LocalSocket或者共享内存的方式.两种方式的基本思路几乎相同,我自己的接收程序是64位的,另外在写一个32位的server程序,负责调用银江的数据接口dll,server程序接收到数据以后,以上面两种方式传递给我64位的接收程序就能够了. 
        首先以LocalSocket的方式来设计接口的,由于共享内存方式会设计比較麻烦的进程间同步问题,localsocket本身就有一条同步信号机制可供使用,详细涉及使用QT的QLocalSocket,QLocalServer类,网上资料非常多,不赘述.既然是首先提这样的方式,肯定是由于终于没选他,理由是,localsocket会把我传的整块数据随即切割,须要我在接收端推断并又一次合成原始完整块数据.这就要求接收端多余的推断操作,和内存创建销毁操作,终于还是放弃了.当然我并没有太深入的去学习localsocket这样的方式有没有办法不自己主动切割发送的完整大块数据,假设有的话,这应该是一种理想的方式.
        以下就要讲讲我终于採用的共享内存方式了,主要涉及QT的QSharedPointer类,开3个共享内存;
        第1个用来存储接收到的数据块.
        第2个用来放接收端(64位)的winid,主要是提供给发送32位的dll调用端读取,在接收到数据后通知64位的接收端有新的数据须要从共享内存中读取;
        第3个共享内存区是同步信号区,存了一个整型变量,1代表等待64位client读取数据,0代表没有须要client读取的数据.程序的初始状态这个值为0,32位server端接收到新数据后,会先进入一个轮询过程,在这个值为1时一直等待,仅仅有在这个值为0的时候才会打开数据共享区,并将数据放入共享区,之后再将这个值置为0.并发送给64位client通知消息(用windows的API,函数PostMessageW,里面目标窗体句柄就是第2个共享区中的数据);之后client收到消息以后,会先去读取共享内存中的数据,将起copy到本地进程中,然后置这里的信号量置为0.
        共享内存方式基本就如上所述了,当然中间还是会有点小问题,由于接收到银江数据头是以下这种结构:
        typedef struct tagRCV_DATA
{
int m_wDataType; // 文件类型
int m_nPacketNum; // 记录数,參见注一
RCV_FILE_HEADEx m_File; // 文件接口
BOOL m_bDISK; // 文件是否已存盘的文件
union
{
RCV_REPORT_STRUCTEx * m_pReport;
RCV_HISTORY_STRUCTEx * m_pDay;
RCV_MINUTE_STRUCTEx * m_pMinute;
RCV_POWER_STRUCTEx * m_pPower;
void * m_pData; // 參见注二
};
} RCV_DATA,*PRCV_DATA;
        能够看出最后一个是个指针,这个指针指实际上在32位server端指向的是这个数据头以下的紧接着的内存地址,可是这个地址是server进程中的绝对地址,到了64位client,假设仍然依照这个值,就不可能得到正确的数据,所以client不应该用这个值来对兴许的数据訪问,而是在copy下来已经在本进程内存中的数据包的首地址上加上RCV_DATA这个数据包头的大小(这里是288字节),这样才干得到正确的兴许数据地址.
原文地址:https://www.cnblogs.com/wgwyanfs/p/6952873.html