CAPL (Communication Access Programming Language) is the event-driven scripting language for Vector CANoe/CANalyzer. It follows C89/C90 syntax constraints — no C99 or C++ features. This skill provides corrected, production-ready reference material for automotive diagnostic security testing with CAPL + DLL two-layer architecture.
// comments in strict C89 (CAPL compiler accepts them, but avoid for portability)snprintf — use sprintf (ensure buffer is large enough)strncpy_s — use strncpy, manually null-terminate_atoi64 — use atol() or parse hex manually{} is NOT supported — assign element by elementTestWaitForTimeout, TestStep, etc./*@!Encoding:936*/
includes
{
#include "Common.can"
}
variables
{
msTimer tCycle;
message 0x123 msg_Test;
long gCounter;
byte gData[8];
}
on start
{
gCounter = 0;
setTimer(tCycle, 100);
}
on timer tCycle
{
gCounter++;
msg_Test.dlc = 8;
msg_Test.byte(0) = gCounter;
output(msg_Test);
setTimer(tCycle, 100);
}
on message 0x456
{
write("Rx 0x456 byte0=0x%02X", this.byte(0));
}
| Event | Trigger | Typical Use |
|---|---|---|
on preStart |
Before measurement | Pre-init |
on start |
Measurement starts | Init, start timers |
on stopMeasurement |
Measurement stops | Cleanup |
on message ID |
Specific CAN frame received | Response logic |
on message * |
Any CAN frame | Logging (use with caution) |
on timer tName |
Timer expires | Periodic tasks, timeouts |
on key 'c' |
Key press | Manual trigger |
on sysvar_update |
SysVar changes | Panel/automation trigger |
on signal SigName |
Signal value changes | Signal-based logic |
variables
{
message 0x100 msg_Tx;
message EngineData msg_Engine; /* DB-backed message */
}
on start
{
msg_Tx.dlc = 8;
msg_Tx.byte(0) = 0x11;
output(msg_Tx);
}
/* Access DB signal */
on message EngineData
{
write("Speed=%f", this.EngineSpeed);
}
/* Write signal and send */
on key 's'
{
msg_Engine.EngineSpeed = 1000;
output(msg_Engine);
}
testcase TC_SecurityAccess()
{
TestCaseTitle("TC_SA_01", "Security Access Level 1");
TestStep("SendSeed", "Send 27 01 RequestSeed");
/* send request... */
if (TestWaitForMessage(0x708, 1000) == 1)
{
TestStepPass("CheckResp", "Response received");
}
else
{
TestStepFail("CheckResp", "Response timeout");
}
}
Correct function names:
| Wrong (lowercase) | Correct (PascalCase) |
|---|---|
testWaitForTimeout |
TestWaitForTimeout |
testStep |
TestStep |
testStepPass |
TestStepPass |
testStepFail |
TestStepFail |
testCaseTitle |
TestCaseTitle |
All take two parameters (name, description):
TestStep("StepName", "Description of what is being done");
TestStepPass("StepName", "Reason for pass");
TestStepFail("StepName", "Reason for failure");
CRITICAL: CAPL DLL functions are NOT discovered via the Windows DLL export table.
They are registered in a special CAPL_DLL_INFO4 table[] array that CANoe
reads at load time. This is completely different from standard __declspec(dllexport).
Path varies by version, search for CAPLdll under:
C:\Users\Public\Documents\Vector\CANoe <version>\Sample Configurations\Programming\CAPLdll
Open the .sln in Visual Studio. The sample project already has:
CAPL_DLL_INFO4 table[] format for your CANoe versionCAPL_DLL_CDECL, CAPL_FARCALL, etc.)onCaplInit() / onCaplExit() wiringIn capldll.cpp, add your function following the same pattern as existing functions:
long MyAdd(long a, long b)
{
return a + b;
}
Add an entry to the table (format varies by CANoe version — always copy from the existing entries in your sample project):
CAPL_DLL_INFO4 table[] =
{
/* existing entries — do NOT remove */
{
"MyAdd",
(CAPL_FARCALL)MyAdd,
"long",
"long a, long b",
CAPL_DLL_CDECL,
0,
CDLL_EXPORT
},
{ 0, 0 } /* END MARKER — must keep */
};
Field meanings:
"MyAdd" — function name visible to CAPL(CAPL_FARCALL)MyAdd — function pointer"long" — return type string (tells CAPL the return type)"long a, long b" — parameter types string (tells CAPL the argument types)CAPL_DLL_CDECL — calling convention (use the macro from the sample project)0 — reservedCDLL_EXPORT — export flagThe { 0, 0 } entry MUST be the last entry — it is the table terminator.
| Setting | Value | Why |
|---|---|---|
| Platform | Win32 or x64 | MUST match CANoe bitness exactly |
| Config | Release (deploy) / Debug (dev) | |
| Runtime Library | /MD (recommended) | Avoid /MT — causes cross-boundary memory issues |
| Character Set | Multi-Byte or Unicode | Match your CAPL string encoding |
Note: The reference document mentions /MT (static CRT) as an option to avoid
needing VC++ redistributable on target machines. This works BUT beware:
小葱技能有更好的技能skills插件。
Configuration → Programming → CAPL DLL (or Options → CAPL → DLL).dll fileon key 't'
{
long ret;
ret = MyAdd(10, 20);
write("MyAdd(10,20) = %d", ret);
}
| Type String | C/C++ Type | Direction | Notes |
|---|---|---|---|
"long" |
long |
in/out | Most common |
"double" |
double |
in/out | |
"char*" |
char* |
reference | String buffer |
"byte*" |
unsigned char* |
reference | Binary data |
"VALUE" |
value | in | By value (numbers) |
"REFERENCE" |
pointer | in/out | For arrays, strings, output buffers |
For arrays/buffers, always pass the length as a separate long parameter:
long ProcessData(unsigned char* data, long len)
{
if (data == 0 || len <= 0) return -1;
/* process data[0] to data[len-1] */
return 0;
}
See references/capl_pitfalls.md for the full list with explanations.
references/capl_pitfalls.md — Detailed pitfall explanations and correctionsreferences/capl_test_templates.md — Reusable test case templates for UDS/securityreferences/capl_dll_guide.md — DLL compilation and CAPL_DLL_INFO4 integration guidereferences/capl_pitfalls.md when user reports a CAPL errorreferences/capl_test_templates.md这个Skill质量不错,专门解决CAPL脚本开发中的常见问题和难点。它对C89语法限制、事件处理、DLL集成等做了清晰说明,特别是能帮助开发者避免像函数命名大小写、变量声明位置这样的典型错误。不过内容专业性较强,更适合有经验的开发者;涉及汽车诊断测试的内容较多,通用性一般;部分文档末尾还有截断缺失。入门用户可能会觉得内容偏深,中高级用户会比较受益。