总的步骤:
1.
首先构建解决方案. 把生成的DLL/EXE连同PDB一起放到一个目录中.
CANVAS.DLL + PDB
GDIWRLD.DLL + PDB
GLWRLD.DLL + PDB
MODEL.EXE/DLL + PDB
PROXY.DLL
TANGRAM.EXE + PDB
REGISTER.BAT
UNREGISTER.BAT
建议使用管理员权限操作. 因为涉及操作注册表.
REGISTER.BAT 用来注册组件. UNREGISTER.BAT 用来注销组件.
未解决的问题:
光使用 MODEL.DLL 的话, 没有问题. MODEL.EXE + PROXY.DLL 就会报错. 即 TANGRAM.EXE 的 GDIVISL.CPP 中 CTangramGdiVisual::Initialize, m_pIConnectionPoint->Advise 处报错 0x80040202 也就是 CONNECT_E_CANNOTCONNECT
并且, 把 PROXY.DLL 替换为 作者提供的 PROXY.DLL 就没有问题. (剩下的DLL和EXE都是我自己编译的).
经过调试 TANGRAM.EXE (同时附加到 MODEL.EXE 的进程), 发现 如果用我编译的 PROXY.DLL, 在 TANGRAM.EXE 进程中 CTangramModelEventSink::QueryInterface 返回 S_OK,
但到了 MODEL.EXE 进程中 就变成 E_NOINTERFACE 了. 很奇怪. 因为 PROXY.DLL 要负责进程间 RPC, 所以肯定是 PROXY.DLL 的问题. 我用 PE EXPLORER 查看了我编译的 PROXY.DLL 和作者提供的 PROXY.DLL
的区别 (或者用 dumpbin /imports /out:proxyimports.txt proxy.dll), 发现我的 PROXY.DLL 少了如下的 IMPORTS:
EF NdrSimpleStructMarshall
77 NdrConformantArrayBufferSize
ED NdrSimpleStructBufferSize
F1 NdrSimpleStructUnmarshall
F8 NdrStubInitialize
79 NdrConformantArrayMarshall
7B NdrConformantArrayUnmarshall
D7 NdrProxyGetBuffer
F7 NdrStubGetBuffer
D8 NdrProxyInitialize
D6 NdrProxyFreeBuffer
D9 NdrProxySendReceive
90 NdrConvert
我不知道这是不是导致问题的原因. 因为作者链接 PROXY.DLL 的时候用了 RPCNDR.LIB, 但是现在 RPCRT4.LIB 已经完全取代了 RPCNDR.LIB.
如果有哪位高手解决了这个问题. 请通知我! 万分感激!
INSIDE COM 最后一章 例子, VS2013 项目下载地址:
http://pan.baidu.com/s/1pJ8awcz
INSIDE COM 光盘源码下载地址:
http://pan.baidu.com/s/1dDG2vkd
2.
未完成:
Proxy.mak
搜索 VS 2013 Custom Build and Clean up Rule
https://msdn.microsoft.com/en-us/library/7s88b19e.aspx
https://social.msdn.microsoft.com/Forums/zh-CN/3f886933-e7dc-4b4f-bd34-9c9efa271471/custom-build-rules-in-vs2010?forum=msbuild
好像, 用 "项目属性 -> 配置属性 -> 自定义生成工具" 就可以解决这个问题
----------------------------------------------
笔记:
参考资料:
http://blog.csdn.net/lllxy/article/details/4277642
http://www.cnblogs.com/qrlozte/p/4173730.html
注: 有些解决方案很明显的编译链接错误就没有记录在这里.
1.
如果系统管理员权限设置的比较严格的话, 要用管理员权限打开 Tangram.exe
首先设置好项目依赖关系:
Canvas
Model 依赖 Canvas
GdiWrld 依赖 Model, Canvas
GLWrld 依赖 GdiWrld, Model, Canvas
Tangram 依赖 GdiWrld, GLWrld, Model, Canvas
除了 Tangram 以外, 其他项目都使用多字节字符集, Tangram 使用 UNICODE字符集 (原因见 5.4)
现在开始 设置 Canvas 项目:
1.1
打开 IDL 筛选器, 挨个把 IDL 文件移除重新添加(因为实际文件是大写名称, 这样才匹配, 主要是我强迫症), 查看 idl 文件的属性, 把 "配置属性 -> 常规 -> 项类型" 修改为 "MIDL 工具"
项目属性 -> 配置属性 -> MIDL -> 与 MkTypLib 兼容 -> 设为 "否"
参考: http://www.cnblogs.com/qrlozte/p/4995462.html
1.2
项目属性 -> 配置属性 -> MIDL -> 附加包含目录 -> 把 "IDL" 文件夹包含进来
项目属性 -> 配置属性 -> C/C++ -> 附加包含目录 -> 添加以下目录:
COMMON
SHARE
1.3
项目属性 -> 配置属性 -> MIDL -> 输出 -> 设置如下:
输出目录 : ..\SHARE
头文件 : %(Filename).h
DllData 文件 : %(Filename)_dlldata.c
IID 文件 : %(Filename).c
代理文件 : %(Filename)_P.c
1.4
把 解决方案资源管理器 中的 Share 筛选器中的 2个 .c 文件去掉, 把 SHARE 文件夹中
的 CANVAS_C.c, CANVAS_I.c 添加进来 (需要运行 MIDL 编译一次)
CANVAS_C.c - this ALWAYS GENERATED file contains the IIDs and CLSIDs, generated from CANVAS_C.IDL
CANVAS_I.c - this ALWAYS GENERATED file contains the IIDs and CLSIDs, generated from CANVAS_I.IDL
CANVAS_I_P.c - this ALWAYS GENERATED file contains the proxy stub code, generated from CANVAS_I.IDL
这个文件是单独用来生成 Proxy.dll 的, 不要包含到项目中!
参考: https://groups.google.com/d/topic/microsoft.public.platformsdk.com_ole/kTvbdBOrJpg
天朝局域网用户请看 cn.bing.com 的 CACHE: http://cncc.bingj.com/cache.aspx?q=CStdStubBuffer+release+4&d=4683049169070810&mkt=zh-CN&setlang=en-US&w=2RII6_hRiF9RmvKBYgFRwyJPrioAp5e7
因为只有 Model.EXE 需要 Proxy/Stub (与 Tangram.exe 进行通信), 所以实际上除了 Model 项目需要生成 Proxy.dll 之外, 其他项目都不需要生成 Proxy.dll
Model 项目生成 Proxy.dll 可以用 VS 中的命令行来实现. 参考 "Custom Build and Clean up"
作者已经提供了一个 Proxy.mak 来生成 Proxy.dll (见 Model 项目)
1.5
现在 Canvas 项目应该可以成功构建了
2.
Model 项目
2.1 - 2.3 参考 1.1 - 1.3
2.4
编译 idl 文件. 把生成的 EVENT_I.C, MODEL_C.C, MODEL_I.C 包括到 Share 筛选器中
2.5
把 CEnumConnectionPoints::CEnumConnectionPoints , CEnumConnections::CEnumConnections 中的 p 类型改为 CConnectionPointList::const_iterator
2.6
现在 Model 项目应该可以成功构建了
2.7
为了生成 Model.exe 以及对应的 Proxy.dll, 要做如下几件事
2.7.1
对 Proxy.mak 做了一些修改, 主要是几个 IDL 生成的 .c 文件都在 SHARE 文件夹里, 另外删掉了 rpcndr.lib
添加了 clean 逻辑 清理 Proxy.dll, Proxy.lib
2.7.2
生成 -> 配置管理器 -> 选择 解决方案为 LocalServer 配置, 并把除了 Model 以外的所有项目的配置都修改为 Debug
Model 配置为 LocalServer
可见在 Model 项目的预处理器中定义了 _OUTPROC_SERVER_ 宏. 并且配置为生成 MODEL.EXE + PROXY.DLL 而不是 MODEL.DLL
然后对 Model 按照 1.1 - 1.3 进行项目属性的修改.
2.7.3
Custom Build Steps and Build Events
参考: https://msdn.microsoft.com/en-us/library/e85wte0k.aspx
用 "项目属性 -> 配置属性 -> 自定义生成步骤" 添加命令行生成 Proxy.dll.
实际上作者是用的 "项目属性 -> 配置属性 -> 生成事件" 添加命令行 "nmake /f proxy.mak" 生成 Proxy.dll 的
我在 项目属性 -> 配置属性 -> 自定义生成步骤 中添加了清理的命令 "nmake /f proxy.mak clean"来删除生成的 Proxy.dll, Proxy.lib
3.
GdiWrld 项目
3.1 - 3.3 参考 1.1 - 1.3
3.4
把筛选器 Share 中的 Canvas_C.c, canvas_i.c 移除, 添加 SHARE 中的 CANVAS_C.C, CANVAS_I.C
编译 idl 文件. 把生成的 XXX_I.C, XXX_C.C 包括到 Share 筛选器中
再把 SHARE 中的 EVENT_I.C 也添加到 Share 筛选器中
3.5
现在 GdiWrld 项目应该可以成功构建了
4.
GLWrld 项目
4.1 - 4.3 参考 1.1 - 1.3
4.4
把作者提供的 GLAUX.LIB 和 GLAUX.H 放到项目文件夹中 (建议创建子文件夹 LIB)
并做好此项目对 GLAUX.H 以及 GLAUX.LIB 的引用
4.5
项目属性 -> 配置属性 -> 链接器 -> 高级 -> 映像具有安全异常处理程序 -> 设为 否 (为了与作者提供的 GLAUX.LIB 兼容)
4.6
好, 现在 GLWrld 项目应该可以成功构建了
5.
现在来配置 Tangram
5.1
项目属性 -> 配置属性 -> 常规 -> 字符集 -> 选择 UNICODE字符集
5.2
项目属性 -> 配置属性 -> C/C++ -> 附加包含目录 -> 添加以下目录:
COMMON
SHARE
5.3
尝试生成 Tangram, 可以看到 Registry.cpp 和 util.cpp 中有不少对 char* 报错的地方
主要是因为 MFC 现在默认只支持 UNICODE, 要编译非 UNICODE 的话必须下载非UNICODE的MFC库.
为了因为 Registry.cpp 和 util.cpp 是 前面 4 个项目都要用到的. 为了不影响另外4个项目.
删除 Tangram 项目的 Common 筛选器
复制 Registry.cpp 和 Util.cpp 以及其对应的头文件到 Tangram 目录下, 修改为 UNICODE 版本 (命名方面, 我加了 _U 后缀以示区别)
5.4
把 ConfigDlg.cpp 中 getFriendlyName 的 sprintf(szKeyBuf, "CLSID\\%s", szCLSID) ; 修改为:
wsprintf(szKeyBuf, _T("CLSID\\%s"), szCLSID) ;
类似的修改还有很多. 此处不一一列举. 总的原则就是把 char 用 TCHAR 或者 LPTSTR 或者 LPCTSTR 替换.
以及一些只能操作 char 的函数用 对应的 TCHAR 函数替换.
然后在必要的地方加上 _T() 宏
在 Registry_U.cpp 的 CLSIDtochar 中有比较重要的修改
5.5
...
INSIDE COM 最后一章例子 TANGRAM 编译笔记
原文:http://www.cnblogs.com/qrlozte/p/5001602.html