当前位置: 代码迷 >> 综合 >> CANoe DLL编程(二)—— CANoe创建DLL
  详细解决方案

CANoe DLL编程(二)—— CANoe创建DLL

热度:96   发布时间:2023-09-20 13:15:39.0

? 相关文章

CANoe DLL编程(二)—— CANoe创建DLL

  • ?CANoe DLL编程(一)—— Visual Studio 创建DLL以及动态调用

  • ?CANoe DLL编程(三)——DLL和回调函数

  • ?CANoe DLL编程(四)——SendKey DLL的CANoe应用

  • ?CANoe DLL编程(五)——通过VS 生成 SendKey.dll

  • ?CANoe DLL编程(六)—— DLL 的二次封装

  • ?本章节内容演示源码下载,点击跳转?


?前言

  • 上一节我们已经掌握了怎么用VS创建一个DLL以及在VS中调用使用。

  • 本节我们通过Vector的官方Demo来学习下CANoe中DLL的规则和语法.

  • 软件环境:
    win10 x64
    visual studio 2019
    CANoe 11 x64


CANoe DLL编程(二)—— CANoe创建DLL

文章目录

  • ? 相关文章
  • ?前言
  • ? Vector 官方DLL Demo结构理解
  • ? Vector 官方DLL Demo源码解读
    • ? 代码初步理解
    • ? C++函数到CAPL可识别函数的映射表 `CAPL_DLL_INFO4`
    • ? C++数据类型和CAPL数据类型的映射规则
  • ?总结

CANoe DLL编程(二)—— CANoe创建DLL


? Vector 官方DLL Demo结构理解

1?? Vector Demo的路径如下C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 11.0.55\Programming,因为我们在学习时有可能会对源码造成破坏,所以我们先copy一份

CANoe DLL编程(二)—— CANoe创建DLL


2?? 打开CANoe工程之后,什么都不做,先Run下,看下打印信息,明白这个工程干什么的,大致意思就是DLL里面定义了很多函数,然后按不同按键,调用不同函数。

CANoe DLL编程(二)—— CANoe创建DLL


3?? 打开capldll.can 看下源码,在includes中它有个编译预处理,判断canoe是 x64 位还是 32位,然后选择不同的DLL

这就很离谱的是:我的window系统是64位的 ,CANoe软件是64的,但是根据打印结果,可以看出脚本打印的却是32位的,不知什么原因,所以我们用VS生成DLL,也应该选择32位平台

CANoe DLL编程(二)—— CANoe创建DLL


4?? 我想尝试下我自己生成的DLL,能不能正常使用;因为我用的是VS2019,我就打开VS 2017 Project,不添加任何代码,然后将输出平台改成X86平台的

CANoe DLL编程(二)—— CANoe创建DLL


5?? 直接点击build 有可能报错如下图,如果报了这个错误,那就按下图设置下。

然后再点击build 生成 Debug\capldll.dll ,将这个dll copy到 canoe工程 CAPLdll - Copy\EXAMPLE\EXEC32路径下替换掉原来的capldll.dll,然后关闭重启CANoe,RUN下如果不报错就说明我们自己生成的DLL也是没问题。

CANoe DLL编程(二)—— CANoe创建DLL


CANoe DLL编程(二)—— CANoe创建DLL


CANoe DLL编程(二)—— CANoe创建DLL

? Vector 官方DLL Demo源码解读

? 代码初步理解

1?? 我们先了解下 on preStarton start 中的代码,除了一些打印,就有两个重要函数

  • registerCAPLDLL 这个函数的作用是初始化CAPL DLL;并返回一个引用dword了类型的句柄,
  • 它还说了,这是考虑到你有可能再其它的node脚本中也引用了相同的DLL,为了不干扰,就分配了不同的句柄
  • 而且这个句柄值还将作为回调函数的参数(下章将细说回调函数)
  • dllInit(gHandle) 初始化

CANoe DLL编程(二)—— CANoe创建DLL


2?? 下图是源码中最为关键,为什么VS创建的DLL,CANoe不能直接用,因为CANoe 有自己的一套规则

  • C++中定义的函数要经过CAPL_DLL_INFO4配置成CANoe可以识别的类型,这个映射关系这就是CANoe创建DLL的核心点
  • CAPL_DLL_INFO4 是一个结构体类型,有九个参数
  • CAPL_DLL_INFO4 table[] 结构体数组,table中配置了多少函数,那么再CANoe中引用这个DLL时就可以使用多少函数;也许你在C++脚本中写了100个函数,但是你在table中就定义了10个函数,那么你在CANoe中就只能使用这10个

CANoe DLL编程(二)—— CANoe创建DLL


3?? 下图这九个参数的具体含义解释

typedef struct CAPL_DLL_INFO4{
    char              cdlName[MAX_CDL_NAME2];        // 在CAPL中调用时显示的函数名CAPL_FARCALL      adr;                           // 函数地址,即vs工程中函数定义时的函数名const char*       categoryName;                  // 函数在CAPL中的所属目录,可以用于对函数的分类const char*       hintText;                      // 对该函数功能的描述介绍(在CAPL中显示)char              resultType;                    // 函数的返回值类型,用CAPL中的类型的首字母大写去表示int               parCount;                      // 函数的参数个数char              parTypes[MAXCAPLFUNCPARS_8_1]; // 函数的参数类型,用CAPL中的类型的首字母大写去表示unsigned char     array[MAXCAPLFUNCPARS_8_1];    // 函数的参数是否是数组:\001表示是1维数组;\002表示2维数组。默认则为\000,可省略,表示常量const char*       parNames[MAXCAPLFUNCPARS_8_1]; // 函数显示的参数名(在CAPL中的声明介绍时)
} CAPL_DLL_INFO4;

CANoe DLL编程(二)—— CANoe创建DLL


? C++函数到CAPL可识别函数的映射表 CAPL_DLL_INFO4


4?? 我们在table中新增一行,让它仍然指向appAdd这个函数,但是我们改了三个参数,待会重新build一下,去CANoe工程中看下有什么区别

  • 参数1: // 在CAPL中调用时显示的函数名
  • 参数2: // 函数地址,即vs工程中函数定义时的函数名
  • 参数3: // 函数在CAPL中的所属目录,可以用于对函数的分类
  • 参数4: // 对该函数功能的描述介绍(在CAPL中显示)
  {
    "dllAdd",            (CAPL_FARCALL)appAdd,           "CAPL_DLL","This function will add two values. The return value is the result",'L', 2, "LL", "", {
    "x","y"}},{
    "dll_test_Add",      (CAPL_FARCALL)appAdd,           "TEST_DLL","just for test",'L', 2, "LL", "", {
    "x","y"}},

CANoe DLL编程(二)—— CANoe创建DLL


5?? 我们把刚才重新build的dll从新copy到 CANoe工程 CAPLdll - Copy\EXAMPLE\EXEC32路径下替换掉原来的capldll.dll,然后关闭重启CANoeCAPL Browser

  • layout 菜单栏中调出CAPL Function,可以看到我们刚才添加的一行代码,和之前有什么不同
  • 函数的分类多了一个新建的TEST_DLL
  • 多了一个函数dll_test_Add,可以在capl脚本中尝试下,和dllAdd 功能是一样的
  • 函数的解释说明
  • 请仔细的和上一步骤我们的设置惊醒对比,加强理解

CANoe DLL编程(二)—— CANoe创建DLL

CANoe DLL编程(二)—— CANoe创建DLL


? C++数据类型和CAPL数据类型的映射规则

6?? 涉及到C++数据类型和CAPL数据类型的差异性, CANoe通过参数5-9定义了一套数据类型的映射规则

  • 参数5: //函数的返回值类型,用CAPL中的类型的首字母大写去表示
  • 参数6: // 函数的参数个数
  • 参数7: // 函数的参数类型,用CAPL中的类型的首字母大写去表示
  • 参数8: // 函数的参数是否是数组:\001表示是1维数组;\002表示2维数组。默认则为\000,可省略,表示常量
  • 参数9: // 函数显示的参数名(在CAPL中的声明介绍时)

  • 下图是CAPL的数据类型和C++的数据类型对比,然后再table中用大写首字母表示
  • 函数参数最多支持64个参数,没人能用那么多吧。。。

CANoe DLL编程(二)—— CANoe创建DLL


7?? 下面的代码很重要,很重要,很重要,基本包括了参数的所有类型。


/***************************参数是常量的情况***********************************/
long CAPLEXPORT far CAPLPASCAL appAdd(long x, long y)
{
    long z = x + y;return z;
} 'L', 2, "LL", "", {
    "x","y"} //参数都是常量,可以省略\000/***************************参数是一维数组的情况***********************************/void CAPLEXPORT far CAPLPASCAL appPutDataTwoPars( unsigned long numberBytes,const unsigned char dataBlock[] )
{
    unsigned int i;for (i = 0; i < numberBytes; i++) {
    dlldata[i] = dataBlock[i];}
}'V', 2, "DB", "\000\001", {
    "noOfBytes","datablock"}/***************************参数是二维数组的情况***********************************/void CAPLEXPORT far CAPLPASCAL appPutDataTwoPars_2( unsigned long numberBytes,const unsigned char dataBlock[],const unsigned char dataBlock_2[][] )
{
    unsigned int i;for (i = 0; i < numberBytes; i++) {
    dlldata[i] = dataBlock[i];}
}'V', 3, "DBB", "\000\001\002", {
    "noOfBytes","datablock",dataBlock_2}/***************************参数是指针的情况***********************************/void CAPLEXPORT far CAPLPASCAL appSum(long i, long j, long* s)
{
    *s = i + j;
}'V', 3, {
    'L', 'L', 'L' - 128}, "", {
    "i", "j", "s"} 

8?? 因为官方demo中没有传递指针的情况,下面我们添加一个实例函数

//添加一个 求和函数
void CAPLEXPORT far CAPLPASCAL appSum(long i, long j, long* s)
{
    *s = i + j;
}//table中定义
{
    "dll_test_Sum",      (CAPL_FARCALL)appSum,           "TEST_DLL","Sum via reference parameter",'V', 3, {
    'L', 'L', 'L' - 128}, "", {
    "i", "j", "s"} },
//重新build之后,再capl中添加代码,可以打印sum的值。
on key '2'{
    long sum ;writeLineEx(1,1,"");writeLineEx(1,1,"<2> Sum via reference parameter");dll_test_Sum(10,20,sum);writeLineEx(1,1,"Call CAPL DLL Function dll_test_Sum() Result = %d ",sum);
}

CANoe DLL编程(二)—— CANoe创建DLL

End

?总结

CANoe DLL编程(二)—— CANoe创建DLL

CANoe DLL编程(二)—— CANoe创建DLL

? 有需要演示中所用demo工程的,可以关注下方公众号网盘自取啦,感谢阅读。
CANoe DLL编程(二)—— CANoe创建DLL

  • ?要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!

  • ? 有手机的小伙伴可以加下交流群,在车载诊断领域的一个小小圈子,群里有网盘资料源码,可能有你需要的呢,平时可以交流技术,聊聊工作机会啥的。

  • ?如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
    CANoe DLL编程(二)—— CANoe创建DLL