通常情况下,对一个标准的com组件进行集成,网上普遍使用的方式有:

1、#import *.dll 或 #import *.ocx的方式,VS编译器重新编译后,就会自动生成组件对应的*.tlh文件,该文件类似于头文件,含有com组件中的接口信息,在自己的项目中就可以引用接口或者类了。
2、#pragma comment(lib, "*.lib")的方式,这种方式可以直接引用lib里的接口声明。

好巧不巧:项目中碰到的三方组件恰好用这两种方式都不能集成:用第一种方式,VS生成的tlh文件内容是空的;第二种直接引用后,编译报错

通过三方组件给的C#调用的示例程序,发现该组件的目标运行平台必须选定是X86平台

自身项目属于C++范畴,所以在查阅部分资料后,遇到了C++/CLI

#include <Windows.h>

#include <stdio.h>

// 在做类型转换时用到
using namespace System; // 组件的路径放在了本地,在实际运行中,将该组件放在了和运行程序的同目录下
#using "E:\C_backup_20180315\jzbank\CallComSln\CallCom\Debug\Interop.SmartCardLib.dll" // SmartCardLib是Interop.SmartCardLib.dll内的命名空间
using namespace SmartCardLib; // 组件的路径放在了本地,在实际运行中,将该组件放在了和运行程序的同目录下
#using "E:\C_backup_20180315\jzbank\CallComSln\CallCom\Debug\Interop.IObjectSafetyTLB.dll" // IObjectSafetyTLB是Interop.IObjectSafetyTLB.dll内的命名空间
using namespace IObjectSafetyTLB; // 时间工具
static SYSTEMTIME t; void main(){ // clsSmartCardClass是namespace SmartCardLib里的
// cli语法 注意 ^ 和 gcnew
clsSmartCardClass ^instance = gcnew clsSmartCardClass(); int ret = -; // namespace SmartCardLib里声明的方法
ret = instance->Connect("param1"); Sleep(); // cli语法 声明变量并初始化
System::Object^ cardNo = gcnew System::Object();
System::Object^ customNo1 = gcnew System::Object();
System::Object^ orderdate1 = gcnew System::Object();
System::Object^ orderAmount1 = gcnew System::Object(); System::Object^ orderNum1 = gcnew System::Object();
System::Object^ orderTotal1 = gcnew System::Object();
System::Object^ fgs1 = gcnew System::Object();
System::Object^ glz1 = gcnew System::Object(); System::Object^ cardStatus1 = gcnew System::Object();
System::Object^ cardPwd1 = gcnew System::Object();
System::Object^ cardType1 = gcnew System::Object();
System::Object^ chgPwd1 = gcnew System::Object(); // Int32
int result = instance->readCard(cardNo, customNo1, orderdate1, orderAmount1,
//
orderNum1, orderTotal1, fgs1, glz1,
//
cardStatus1, cardPwd1, cardType1, chgPwd1); // 文件生成在本地,临时写在特定目录
FILE *pFile;
fopen_s( &pFile, "C:\\Users\\Administrator\\teller\\device\\1\\infofile\\info.txt", "w+" ); if (result == )
{
char resv[] = {}; //////////////////////////////////////////////
// cli语法 将 System::String^ 转换为 char*
strcpy(resv, (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi((System::String^)cardNo));
printf("\nok, instance->readCard()-----------cardNo=%s", resv); GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %s\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, resv);
fflush(pFile); memset(resv, , sizeof(resv)); //////////////////////////////////////////////
strcpy(resv, (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi((System::String^)customNo1));
printf("\nok, instance->readCard()-----------customNo1=%s", resv); GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %s\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, resv);
fflush(pFile); memset(resv, , sizeof(resv)); //////////////////////////////////////////////
strcpy(resv, (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi((System::String^)orderdate1));
printf("\nok, instance->readCard()-----------orderdate1=%s", resv); GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %s\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, resv);
fflush(pFile); memset(resv, , sizeof(resv)); //////////////////////////////////////////////
GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %d\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, (int)(System::Int32)orderAmount1);
fflush(pFile);
printf("\nok, instance->readCard()-----------orderAmount1=%d", (int)(System::Int32)orderAmount1); //////////////////////////////////////////////
GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %d\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, (int)(System::Int16)orderNum1);
fflush(pFile);
printf("\nok, instance->readCard()-----------orderNum1=%d", (int)(System::Int16)orderNum1); //////////////////////////////////////////////
GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %d\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, (int)(System::Int32)orderTotal1);
fflush(pFile);
printf("\nok, instance->readCard()-----------orderTotal1=%d", (int)(System::Int32)orderTotal1); //////////////////////////////////////////////
strcpy(resv, (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi((System::String^)fgs1));
printf("\nok, instance->readCard()-----------fgs1=%s", resv); GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %s\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, resv);
fflush(pFile); memset(resv, , sizeof(resv)); //////////////////////////////////////////////
strcpy(resv, (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi((System::String^)glz1));
printf("\nok, instance->readCard()-----------glz1=%s", resv); GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %s\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, resv);
fflush(pFile); memset(resv, , sizeof(resv)); //////////////////////////////////////////////
strcpy(resv, (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi((System::String^)cardStatus1));
printf("\nok, instance->readCard()-----------cardStatus1=%s", resv); GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d %s\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, resv);
fflush(pFile);
}
else
{
GetLocalTime(&t);
fprintf(pFile, "%4d/%02d/%02d %02d:%02d:%02d.%03d call readCard faild, ret=%d\n",
t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute, t.wSecond,t.wMilliseconds, result);
} fflush(pFile);
fclose(pFile);
pFile = NULL; int dret = instance->Disconnect();
//printf("\n--, instance->Disconnect()-----------dret=%d", dret); // 此处延时会导致程序即将结束时报错:Runtime error 217 at 。。。
//Sleep(3000); //getchar();
}

在C++项目中调用如下:

#include "LoadDll.h"

#include <ShlObj.h>

//用于生成文件夹 mkdir
#include <direct.h>
#include <string.h> char exePath[MAX_PATH] = {};
ret = checkExePath(exePath, exeName);
if(ret < ) return ret; char params[] = {};
sprintf(params,
"%s|%d|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
funcName, timeout, compcode,
tmpCardNo, tmpcustomNo,
orderdate, orderNum, orderAmount,
orderTotal, tmpCardPwd, alertLowLimit,
overDraft, idleDays, upLimit
); ret = CallExe(exePath, params, timeout); // 读取生成的文件
char infoFilePath[MAX_PATH] = {};
ret = checkExePath(infoFilePath, txtName);
if(ret < ) return ret; FILE *pInfoFile = fopen(infoFilePath, "r");
if(NULL == pInfoFile) return -; char output[] = {};
fgets(output, sizeof(output), pInfoFile); fflush(pInfoFile);
fclose(pInfoFile);
pInfoFile = NULL; // 删除临时生成的文件
//ret = remove(infoFilePath);

其中CallExe函数实现为:

int CallExe(char exePath[], const char* params, int timeout)
{
SHELLEXECUTEINFO exe = {}; exe.cbSize = sizeof(SHELLEXECUTEINFO);
exe.fMask = SEE_MASK_NOCLOSEPROCESS;
exe.hwnd = NULL;
exe.lpVerb = NULL;
exe.lpFile = exePath;
exe.lpParameters = params;
exe.lpDirectory = NULL;
//exe.nShow = SW_NORMAL;
exe.nShow = SW_HIDE;
exe.hInstApp = NULL; BOOL suc = ShellExecuteEx(&exe); DWORD m = WaitForSingleObject(exe.hProcess, timeout * ); return (int)m; }

其中checkExePath函数实现为:

int checkExePath(char exePath[], char* fileSimpleName)
{
char path[MAX_PATH] = {};
if (GetDesktopPath(path)){ int desktopPathLenth = strlen((const char *)path); int i = desktopPathLenth - ;
for(; i > ; i--){
if(path[i] == '\\' || path[i] == '/'){
break;
}
} for(int j = ; j < i; j++){
exePath[j] = path[j];
} sprintf(exePath, "%s%s", exePath, "\\fold1"); // 检查“teller”文件夹是否存在
if (!CheckFolderExist(exePath)){
_mkdir(exePath);
} sprintf(exePath, "%s%s", exePath, "\\fold2"); // 检查“device”文件夹是否存在
if (!CheckFolderExist(exePath)){
_mkdir(exePath);
} sprintf(exePath, "%s%s", exePath, "\\fold3"); // 检查“CNG_READER_JZBANK”文件夹是否存在
if (!CheckFolderExist(exePath)){
_mkdir(exePath);
} // 用户目录/fold1/fold2/fold3/fileSimpleName
sprintf(exePath, "%s\\%s", exePath, fileSimpleName);
// 检查exe是否存在 return ;
} return -;
}

GetDesktopPath的函数实现为:

//获取桌面目录的绝对路径
bool GetDesktopPath(char* desktopPath)
{
if (SHGetSpecialFolderPath(NULL, desktopPath, CSIDL_DESKTOP, )){
return TRUE;
} return FALSE;
}

CheckFolderExist的函数实现为:

//目录是否存在的检查:
bool CheckFolderExist(const char* strPath)
{
WIN32_FIND_DATA wfd;
bool rValue = FALSE;
HANDLE hFind = FindFirstFile(strPath, &wfd);
if ((hFind != INVALID_HANDLE_VALUE) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
rValue = TRUE;
}
FindClose(hFind);
return rValue;
}

C++\CLI语法 在项目中的使用的更多相关文章

  1. 项目中lua(基础)

    关于项目中lua任务(某些没弄懂,但lua上耗费时间有点长了不看了) 这段时间看了lua语法和项目中lua应用 .在lua中注册c库,在lua5.2中好像都是注册c库,相当于在lua中定义一个tabl ...

  2. 项目中oracle存储过程记录——经常使用语法备忘

    项目中oracle存储过程记录--经常使用语法备忘 项目中须要写一个oracle存储过程,需求是收集一个复杂查询的内容(涉及到多张表),然后把符合条件的记录插入到目标表中.当中原表之中的一个的日期字段 ...

  3. scss/less语法以及在vue项目中的使用(转载)

    1.scss与less都是css的预处理器,首先我们的明白为什么要用scss与less,因为css只是一种标记语言,其中并没有函数变量之类的,所以当写复杂的样式时必然存在局限性,不灵活,而scss与l ...

  4. vue之cli脚手架项目中组件的使用

    在webpack-simple模板中,包括webpck模板.一个.vue文件就是一个组件. 为什么会这样呢?因为webpack干活了!webpack的将我们所有的资源文件进行打包.同时webpack还 ...

  5. nuxt 脚手架创建nuxt项目中不支持es6语法的解决方案

    node本身并不支持es6语法,我们通常在vue项目中使用es6语法,是因为,我们使用babel做过处理, 为了让项目支持es6语法,我们必须同时使用babel 去启动我们的程序,所以再启动程序中加 ...

  6. 关于CUDA C 项目中“ error C2059: 语法错误:“<” ”问题的解决方法

    该问题的关键在于理解CUDA项目中C\C++文件需要由c++编译器进行编译,而CUDA C的源文件需要由CUDA的编译器nvcc.exe进行编译. 发生该语法错误的原因是cu文件被C++编译器所编译, ...

  7. Vue 项目中的ESlint语法报错问题

    在项目中的""和;经常会报错,真的很纠结,今天看到一个解决方法,可以不用卸载删除 在项目根目录中,新建一个.prettierrc文件,来移除分号,和替换为单引号. { " ...

  8. Vue项目中sass语法该怎么用?

    最近开始着手Vue框架,被各种报错蹂躏,其中有一个就是sass语法,<style>标签中添加<style lang="scss">,发现报错,在网上找了一些 ...

  9. 解决Vite-React项目中js使用jsx语法报错的问题

    背景 在做存量项目接入Vite测试时发现,存量(老)项目中很多是直接在js中书写jsx语法,使用Vite启动时就会抛出一堆问题Failed to parse source. 不嫌麻烦可以跑个脚本批量修 ...

随机推荐

  1. Gradle打jar包命令

  2. vue服务器端渲染

    Vue.js 是构建客户端应用程序的框架.默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM.然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏 ...

  3. Linux 学习 (八) Shell

    Linux达人养成计划 I 学习笔记 Shell 是什么: Shell 是一个命令解释器 Shell 还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强 Shell 的分类: Bourne S ...

  4. CSS属性速查表

    前面的话 本文将按照布局类属性.盒模型属性.文本类属性.修饰类属性这四个分类,对CSS常用属性进行重新排列,并最终设置为一份stylelintrc文件 布局类 1.定位 position z-inde ...

  5. ORM关于表那些事

    一.. ORM表和表之间的关系 1. 一对多 --> 外键(ForeignKey) 2. 多对多 --> 另外一张关系表(ManyToManyField) 1. 三种方式 1. 自己建立第 ...

  6. 当同时安装Python2和Python3后,如何兼容并切换使用详解(比如pip使用)

    由于历史原因,Python有两个大的版本分支,Python2和Python3,又由于一些库只支持某个版本分支,所以需要在电脑上同时安装Python2和Python3,因此如何让两个版本的Python兼 ...

  7. python的内置模块xml模块方法 xml解析 详解以及使用

    一.XML介绍 xml是实现不同语言或程序直接进行数据交换的协议,跟json差不多,单json使用起来更简单,不过现在还有很多传统公司的接口主要还是xml xml跟html都属于是标签语言 我们主要学 ...

  8. GO语言系列(二)- 基本数据类型和操作符

    一.文件名 & 关键字 & 标识符 1.所有go源码以.go结尾 2.标识符以字母或下划线开头,大小写敏感 3._是特殊标识符,用来忽略结果 4.保留关键字 二.Go程序的基本结构 p ...

  9. 使用Eclipse创建动态的web工程

    使用Eclipse创建动态的web工程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.修改工作区的编码 1>.点击Window选择Preferences 2>.将默 ...

  10. 前端面试题整理—Vue篇

     1.对vue的理解,有什么特点,vue为什么不能兼容IE8及以下浏览器 vue是一套用于构建用户界面的渐进式框架,核心是一个响应的数据绑定系统 vue是一款MVVM框架,基于双向绑定数据,当数据发生 ...