C++: CanlibTutorial, VS2017

This tutorial will take you through setting up a Visual Studio 2017 project and creating an application that will be able to list connected devices.

Setting up a project to use CANlib

In this section we will enable the usage of Kvaser CANlib in Visual Studio 2017 when creating a C++ project which can be used to build both WIN32 and WIN64 applications. We will also handle the platform settings: x86 and x64.

First we must have the "Kvaser Drivers for Windows" and "Kvaser CANlib SDK" installed, see Installing on Windows for details on how to download and install these.

Now we are ready to start Visual Studio 2017 (C++) and create our project (I am using "Microsoft Visual Studio Professional 2017").

Creating an empty project

After starting Visual Studio 2017 (C++), we create a new project by selecting "File–>New->Project...". Choose to create a "Windows Console Application, Visual C++", name it "CanlibTutorial" (the Solution will now also be named "CanlibTutorial"), and press "OK".

cpp_tutorial_1_create_project.png
Creating the CanlibTutorial project

You will now be given an empty main function that does nothing.

cpp_tutorial_2_empty_project.png
The CanlibTutorial project

Adding CANlib

Now we need to do five things to add CANlib so that we can build the project:

  1. The LIB name "canlib32.lib" to Additional Dependencies
  2. Add path to INC (...\Kvaser\Canlib\INC\canlib.h)
  3. Add path to LIB (x86) (...\Kvaser\Canlib\Lib\MS\canlib32.lib)
  4. Add path to LIB (x64) (...\Kvaser\Canlib\Lib\x64\canlib32.lib)
  5. Add #include "canlib.h"

We start by opening "Project->CanlibTutorial Properties..." and in the drop down for "Configuration" we select "All Configurations".

cpp_tutorial_3_linker_input_configuration.png
Use the same configuration for all configurations.

We also do the same for the next drop down selector "Platform" where we select "All Platforms". This might trigger a pop-up informing us that "There are no property pages for the selection".

cpp_tutorial_4_linker_input_no_property.png
VS2017 closes the configuration by giving some information

Press OK and reopen the properties once again using "Project->CanlibTutorial Properties...", in the left pane select "Linker" and then "Input". Now click in the text field to the right of "Additional Dependencies", this will reveal a drop down menu which we select, revealing an <Edit...> text which we click on.

cpp_tutorial_5_linker_additional_dependencies.png
Click the <Edit...> text to start editing the values

This opens up the "Additional Dependencies" where we add "canlib32.lib" in the top text box and press OK.

Note
This applies to all libraries in the canlibSDK (CAN bus API (CANlib), LIN bus API (LINlib), Database API (kvaDbLib), Memorator API (kvmlib), Memorator XML API (kvaMemoLibXML), Converter API (kvlclib), Remote Device API (kvrlib)) which can be included by adding their files to the dependency list.
cpp_tutorial_6_linker_additional_dependencies_editor.png
Adding canlib32.lib to the dependencies.

When the pop-up has been closed, we can now verify that "canlib32.lib" has been added to the "Additional Dependencies" field.

The next step is to add the path to canlib.h. On my machine I installed Kvaser CANlib SDK to "D:\CanlibSDK\CanlibSDK_5.26" (default is "C:\Program Files (x86)\Kvaser\Canlib"), which means that "canlib.h" can be found in "D:\CanlibSDK\CanlibSDK_5.26\INC" (default would be "C:\Program Files (x86)\Kvaser\Canlib\INC").

Once again open up the Property pages (using "Project->CanlibTutorial Properties...") and in the left pane select "C/C++" and "General". Click in the value field for "Additional Include Directories" and add the path to "canlib.h", in my case "D:\\CanlibSDK\\CanlibSDK_5.26". Now press Apply.

cpp_tutorial_7_cpp_general_additional_include.png
Add path to canlib.h to compiler include directories

From the "Platform" drop down selector, select "Win32", which once again closes our window with the pop-up informing us that "There are no property pages for the selection". Press OK and reopen the properties once again using "Project->CanlibTutorial Properties...", in the left pane select "Linker" and "General". Click in the value field for "Additional Library Directories" and add the path to the 32-bit version of "canlib32.lib", in my case "D:\CanlibSDK\CanlibSDK_5.26\Lib\MS" (default is "C:\Program Files (x86)\Kvaser\Canlib\Lib\MS"). Now press Apply.

We repeat the process for the 64 bit version by selecting "x64" as the "Platform" and enter (after reopening the CANlibTutorial properties) "D:\CanlibSDK\CanlibSDK_5.26\Lib\x64" (default is "C:\Program Files (x86)\Kvaser\Canlib\Lib\x64") in the field for "Additional Library Directories". Press OK to save and close the properties.

cpp_tutorial_8_linker_general_additional_library.png
Adding library dependancies to 64-bit platform

Adding the code

The last step is to add #include "canlib.h" to CanlibTutorial.cpp. We do this as well as enter some more code...

//-----------------------------------------------------------
// This is a sample program for the Visual Studio 2017 CANlib tutorial.
// It prints a list of connected CAN interfaces.
//
// For further information please refer to the tutorial section of the CANlib documentation.
//-----------------------------------------------------------
#include "stdafx.h"
#include "canlib.h"
#include "iostream"
// When called, CheckForError will check for and print any error.
// The program is aborted if an error has occured.
void CheckForError(char cmd[50], canStatus stat)
{
//if stat not ok, print error
if (stat != canOK)
{
char buf[255];
buf[0] = '\0';
canGetErrorText(stat, buf, sizeof(buf));
printf("[%s] %s: failed, stat=%d\n", cmd, buf, (int)stat);
printf("ABORT (Press any key)");
getchar();
abort();
}
}
// ListChannels prints a list of all connected CAN interfaces.
void ListChannels()
{
canStatus stat;
int number_of_channels;
int device_channel;
char device_name[255];
// Get number of channels
stat = canGetNumberOfChannels(&number_of_channels);
CheckForError((char*)"canGetNumberOfChannels", stat);
if (number_of_channels > 0) {
printf("%s %d %s\n", "Found", number_of_channels, "channels");
}
else {
printf("Could not find any CAN interface.\n");
}
// Loop and print all channels
for (int i = 0; i < number_of_channels; i++) {
stat = canGetChannelData(i, canCHANNELDATA_DEVDESCR_ASCII, device_name, sizeof(device_name));
CheckForError((char*)"canGetChannelData", stat);
stat = canGetChannelData(i, canCHANNELDATA_CHAN_NO_ON_CARD, &device_channel, sizeof(device_channel));
CheckForError((char*)"canGetChannelData", stat);
printf("%s %d %s %d\n", "Found channel:", i, device_name, (device_channel + 1));
}
}
int main()
{
//canStatus stat;
printf("%s\n", "CanlibTutorial started");
ListChannels();
return 0;
}

To run the code, select platform from the drop-down menu, and press the green play icon.

cpp_tutorial_9_select_platform.png
Select platform to run, and then press the play icon