Question

I have a DLL that I have ported from VC2008 to C++ Builder XE2. The DLL is used in LabVIEW's TestStand.

TestStand, when importing the VC2008 DLL, can see the function names and their arguments. When using the C++ Builder DLL, all its sees are the function names and not the arguments. All exports are C functions and use extern "C" declspec( dllexport ).

Is there a way to get the exports correct?

I have read that adding a TLB file will do the job, if this is true, how do I create a TLB that exports only C functions?

Was it helpful?

Solution

TestStand can read a .c/.cpp file and derive parameters from that file. You still load the DLL and select the function you want to call. You then 'verify' the parameters and select the .c/.cpp file in the dialog. TestStand will find the function with the same name and insert the parameters itself.

The function must be very specific, I had to create a dummy .c file that contained the prototypes as TestStand could not handle the #defines for dllexport and dllimport. It likes a very specific format. For the function:

TESTAPI bool StartTest( long inNumber ) {}

where TESTAPIis either extern "C" __declspec( dllexport ) or extern "C" __declspec( dllimport I had to write the line below in my dummy file:

bool __declspec( dllexport ) StartTest( long inNumber ) {}

That does it.

OTHER TIPS

DLL function parameters cannot be determined from exports alone, unless they are being decorated by the calling convention (which is unusual to do in a DLL). If a TLB (aka a Type Library) solves the problem, then the VC2008 DLL is likely an In-Process ActiveX/COM object rather than a flat C DLL. If so, then in C+Builder you can use the IDE wizards on the "File | New" menu to create an "ActiveX Library" project, then a "COM Object" to add to the library. Then you will have a TLB that you can define your object with, and the IDE will generate stub code that you can fill in with your object's implementation.

If that is not what LabViews is expecting, then I suggest you contact them and ask. If all it needs is a TLB with flat C functions (which is very unusual, because TLB's are object-oriented), then you can omit the "COM Object" portion and just create an "ActiveX Library" project to get a bare-bones TLB, then add your definitions to it as needed, an then add your exports to the project.

From the reference here:

Avoid using the extern "C" syntax to export symbols. The extern "C" syntax prevents the C/C++ DLL Adapter from obtaining type information for function and method parameters."

A little late to the game, but your problem may be that C++ Builder is decorating the exported function with a leading underscore. The TLIB command line utility should help prove this (assuming tlib still ships with C++Builder)

TLIB mydll.lib, mydll.lst

Look at the resulting lst file and see if it contains StartTest or _StartTest. LabView is probably expecting to find a function without the underscore.

You can add a DEF file to your C++Builder project that will suppress the leading underscore. Try this:

  1. Use the __cdecl calling convention instead of __stdcall.

  2. Export plain "C" functions. No C++ classes or member functions.

  3. Make sure you have an extern "C" {} around your function prototypes.
  4. Create a DEF file that aliases the exported functions to a Microsoft compatible name. Alias the names so they don't contain a leading underscore. The DEF file will look like this:

    EXPORTS ; MSVC name = C++Builder name StartTest = _StartTest Foo = _Foo Bar = _Bar

5- Add the DEF file to your BCB DLL project and rebuild it.

Check out these ancient articles for more details: http://bcbjournal.org/articles/vol4/0012/Using_Visual_C_DLLs_with_CBuilder.htm

The reverse article (creating C++Builder DLLs that get called from VC++ created applications) is buried in this archive:

http://www.frasersoft.net/program/bcbdev.zip : /articles/bcbdll.htm. It describes the DEF file trick in more detail, plus some other options.

Note that my answer is based on the way thing were in 1998 or so. They may have changed since then. If they have, then the C++Builder command line tools impdef, tlib, tdump, plus the Microsoft equivalents of those tools, should be able to show you exactly what is in your DLL vs the MSVC one.

H^2

I suggest to use ActiveX object: you can create an automation object in C++Builder and in Labview / TestStand you can import this object. If you use automation, in Lavbiew you will have the correct parameter definition. Make sure you are using a set of compatible type variables with Labview / TestStand. For example, this fragment of code is the implementation of an array passed from Labview to C++:

STDMETHODIMP TCanLibraryImpl::DataDownload(VARIANT Data, long* RV)
{
   _precondition_cmodule();   
   *RV = 0;
   TSafeArrayLong1 mySafeArray(Data.parray);
   int dLen =mySafeArray.BoundsLength[0];
   ...
}

In Labview you will pass to this function an array of I64

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top