Connecting to both K8090 and K8055 simultaneously

Is it possible to connect to both the K8090 and K8055 at the same time from within the same C/C++ program?

Last time I tried this it failed because both the K8055 and K8090 have OpenDevice() and CloseDevice() functions defined which cause a linker conflict.

You’ve provided too little information to give a specific solution, but there should never be any naming problems holding you back. For example C and C++ have namespaces to avoid conflicts with possible duplicate names.

I didn’t know about namespaces :blush: That certainly resolved the linker error.

The following code, however, still fails at the call to K8055::OpenDevice(K8055_CARD_ADR); It just crashes with no error message or explanation - and it makes no difference if the K8055 is actually connected or not. By removing chunks of the code I can get each card to work separately, but not together - and the conflict seems to be with the OpenDevice() functions. Have I missed something?

This code was written using Borland Turbo C++ 2006 and run under Win XP pro SP3:

[code]#include <windows.h>
#include <stdio.h>
#include <wchar.h>

namespace K8090
{
#include “K8090D.h” // Velleman Relay board
}

namespace K8055
{
#include “K8055D_C.h” // Velleman USB interface board
}

#define K8055_CARD_ADR 0 // card address for USB interface board

//---------------------------------------------------------------------------

int PulseChannel8()
{
int return_value = 1; // set return_value for fail by default
int result;
result = K8055::OpenDevice(K8055_CARD_ADR);
if(result == K8055_CARD_ADR)
{
K8055::SetDigitalChannel(8);
Sleep(1000);
K8055::ClearDigitalChannel(8);
K8055::CloseDevice();
return_value = 0;
}
else
printf(“Unable to connect to K8055 USB interface board.\n”);
return return_value;
}

//---------------------------------------------------------------------------

int PulseRelay8()
{
HK8090 hRelay; // handle to K8090 relay board
int return_value = 1; // set return_value for fail by default
hRelay = K8090::OpenDevice(“COM5”);
if ((hRelay != NULL) && (hRelay != INVALID_HANDLE_VALUE))
{
K8090::SendCommand(hRelay, CMD_SWITCH_RELAY_ON, 0x80, 0x00, 0x00);;
Sleep(1000);
K8090::SendCommand(hRelay, CMD_SWITCH_RELAY_OFF, 0x80, 0x00, 0x00);
K8090::CloseDevice(hRelay);
return_value = 0;
}
else
printf(“Unable to connect to K8090 relay board.\n”);
return return_value;
}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])
{
int result;
while(TRUE)
{
result = PulseRelay8();
printf(“8090: %d\n”, result);
getc(stdin);
result = PulseChannel8();
printf(“8055: %d\n”, result);
getc(stdin);
}
return 0;
}
[/code]

I’ve done some more investigating. To get the code in the previous post to run for either the K8090 or the K8055 alone I only have to comment out the call to (respectively) the PulseChannel8() or the PulseRelay8() function. BUT I can only have either the K8090D.lib or the k8055d_c.lib added to the project - when I have both .lib files added to the project is when the trouble starts.

I have tried rebuilding both the .lib files using the Borland IMPLIB utility and the instructions at http://www.tek-tips.com/viewthread.cfm?qid=1099123&page=23 to no avail.

You will need to provide something more concrete like compiler or linker errors :slight_smile:

[quote]BUT I can only have either the K8090D.lib or the k8055d_c.lib added to the project[/quote]That may be just an impression. The actual reason is probably because one of the lib files (i think the K8090 lib file) is not in a compatible format.

Allow me to explain; There are two formats for .lib files: Microsoft format, and Borland format. Since you are using a Borland product, you will not be able to use .lib files in Microsoft format. The .lib file for the K8090 is in Microsoft format since the code for the DLL was written in Microsoft Visual Studio. The DLL for K8055 was (probably) written in Borland Delphi, so that .lib file will be in Borland’s format. That one will be ok to use in Borland Turbo C++.

What is the solution?
Use dynamic linking instead of static linking (GetProcAddress, LoadLibrary), that way you don’t need any .lib files. There are numerous examples on the internet on how to do this. I think you will also be able to find examples on this forum.

Borland provide a utility IMPLIB to generate a compatible LIB file from a DLL. I have used this successfully with the K8090 for some time - see my post under the topic “information comand K8090”.

I have actually now got the K8090 and K8055 to work at the same time, without using namespaces, as follows:

  1. I created a copy of the K8055D_C.h file and modified the declarations for the OpenDevice() and CloseDevice() functions as follows:
FUNCTION long __stdcall K8055_OpenDevice(long CardAddress);
FUNCTION __stdcall K8055_CloseDevice();
  1. Based on the instructions contained at http://www.tek-tips.com/viewthread.cfm?qid=1099123&page=23

2a) I created a DEF file from the K8055 DLL using the command:

IMPDEF K8055D2.DEF K8055D.DLL

2b) I modified the resulting DEF file to add aliased copies of the OpenDevice() and CloseDevice() functions so that the resulting file looked like this:

[code]LIBRARY K8055D.DLL

EXPORTS
ClearAllAnalog @1 ; ClearAllAnalog
ClearAllDigital @2 ; ClearAllDigital
ClearAnalogChannel @3 ; ClearAnalogChannel
ClearDigitalChannel @4 ; ClearDigitalChannel
CloseDevice @5 ; CloseDevice
OpenDevice @6 ; OpenDevice
OutputAllAnalog @7 ; OutputAllAnalog
OutputAnalogChannel @8 ; OutputAnalogChannel
ReadAllAnalog @9 ; ReadAllAnalog
ReadAllDigital @10 ; ReadAllDigital
ReadAnalogChannel @11 ; ReadAnalogChannel
ReadCounter @12 ; ReadCounter
ReadDigitalChannel @13 ; ReadDigitalChannel
ResetCounter @14 ; ResetCounter
SearchDevices @15 ; SearchDevices
SetAllAnalog @16 ; SetAllAnalog
SetAllDigital @17 ; SetAllDigital
SetAnalogChannel @18 ; SetAnalogChannel
SetCounterDebounceTime @19 ; SetCounterDebounceTime
SetCurrentDevice @20 ; SetCurrentDevice
SetDigitalChannel @21 ; SetDigitalChannel
Version @22 ; Version
WriteAllDigital @23 ; WriteAllDigital

K8055_CloseDevice = CloseDevice
K8055_OpenDevice = OpenDevice

[/code]

2c) I then created a Borland compatible LIB file from the modified DEF file using the command:

IMPLIB K8055D2.LIB K8055D2.DEF

and added the resulting LIB file to my project along with the previously created K8090D.lib file.

The following code now works without the need for namespaces:

[code]#include <windows.h>
#include <stdio.h>
#include “K8090D.h” // Velleman Relay board
#include “K8055D2.h” // Velleman USB interface board

#define K8055_CARD_ADR 0 // card address for USB interface board

//---------------------------------------------------------------------------

int PulseChannel8()
{
int return_value = 1; // set return_value for fail by default
int result;
result = K8055_OpenDevice(K8055_CARD_ADR);
if(result == K8055_CARD_ADR)
{
SetDigitalChannel(8);
Sleep(1000);
ClearDigitalChannel(8);
K8055_CloseDevice();
return_value = 0;
}
else
printf(“Unable to connect to K8055 USB interface board.\n”);
return return_value;
}

//---------------------------------------------------------------------------

int PulseRelay8()
{
HK8090 hRelay; // handle to K8090 relay board
int return_value = 1; // set return_value for fail by default
hRelay = OpenDevice(“COM5”);
if ((hRelay != NULL) && (hRelay != INVALID_HANDLE_VALUE))
{
SendCommand(hRelay, CMD_SWITCH_RELAY_ON, 0x80, 0x00, 0x00);;
Sleep(1000);
SendCommand(hRelay, CMD_SWITCH_RELAY_OFF, 0x80, 0x00, 0x00);
CloseDevice(hRelay);
return_value = 0;
}
else
printf(“Unable to connect to K8090 relay board.\n”);
return return_value;
}

//---------------------------------------------------------------------------

int main(int argc, char* argv[])
{
int result;
while(TRUE)
{
result = PulseRelay8();
printf(“8090: %d\n”, result);
getc(stdin);
result = PulseChannel8();
printf(“8055: %d\n”, result);
getc(stdin);
}
return 0;
}
[/code]

Why it wouldn’t work using namespaces I don’t know.

So the culprit was the lib file’s format all along, beautifully solved, good work

All the K8055’s functions seem to be prefixed by “K8055_”, so there probably never was a need for namespaces :slight_smile:

All I have really done is to remove the duplication of the OpenDevice() and CloseDevice() function names in the two header files, by providing and using new names for these in the K8055 .h and .lib files.

Using namespaces should presumably have had the same affect - but it would seem that while the linker was happy (with namespaces) it, or something, was still not putting the code together correctly.

I would also have thought, given that the different OpenDevice() and CloseDevice() functions all had unique argument sets, a smart linker should have been able to connect everything up correctly without either namespaces or aliases.

Anyway we now have a solution :smiley:

[quote=“lynchaird”]I would also have thought, given that the different OpenDevice() and CloseDevice() functions all had unique argument sets, a smart linker should have been able to connect everything up correctly without either namespaces or aliases.[/quote]If I remember correctly, neither the lib file nor the DLL exposes information about a function’s arguments since this is technically not necessary. Depending on which calling convention the DLL uses, the arguments will get pushed and popped off the stack properly. So the linker cannot know, it is also not the linker’s job :slight_smile: But that’s just some information on the side