Three queries, if I may, about using third party Dlls with Liberty Basic. I have Alyce's excellent book on APIs and have downloaded her demos and I have used various APIs in Liberty Basic over the past ten years. The current project involves writing software to interface a Picotech Analogue-to-digital converter to a machine running Windows XP by making calls to Picotech's Dll in their driver. Here are my three questions: 1) Has anyone done this already? If so, any help you can give me would be most welcome. My project is an amateur effort and entirely non-commercial. 2) My problem is that I am not getting the CallDll syntax right because, I think, some of the variables are pointers and I don't know whether LB can accommodate those. One of the simplest C instructions looks like:
PICO_STATUS UsbDrDaqOpenUnit ( short * handle)
I translate this to: Open DrDAQ32.DLL for dll as #DrDAQ CallDll #DrDAQ, "PICO_STATUS UsbDrDaqOpenUnit", hdl as SHORT
This does not work. Perhaps someone might set me right, please? 3) Should I expect that, generally, third party Dlls be accessible to Liberty Basic? If I'm on a hiding to nothing, I might consider writing a program in C which I can call from LB. But it would be good to know. Many thanks. Frank
Should be perfectly doable in Liberty, just need the format of the calls corrected.
If you can find Visual BASIc examples they are usually easier to match up with Liberty. I read some old docs that used LPT1 LPT2 etc. So I assume this is a new USB based version. The command is opening an attached unit. The handle will either be the com port number the unit is using, com11, com13 etc. Or if it is a unique USB connection it is likely to be simply numbered 0,1,2 etc
If the unit is using a comport number you will see that using Windows Device manager (Windows key + X). If it is a wholey USB based connection you can just try 0,1,2 for handle. Most likely a single unit will be 0 or 1
You are opening the dll correctly. I would have thought the subsequent command just needs to be:
handle=13 or handle=0 calldll #DrDAQ,"UsbDrDaqOpenUnit",handle as long, ret as long
The command is supposed to return a value saying connection is ok or giving an error code.
You are supposed to have the docs in a folder, show us any VB examples of the commands you are trying to use. Or the paragraph covering the command.
Post by Chris Iverson on Mar 24, 2021 10:34:41 GMT -5
calldll #DrDAQ,"UsbDrDaqOpenUnit",handle as long, ret as long
Close, but as he said in his post, the handle parameter is a pointer.
LB does not have the ability to directly dereference pointers to numeric variables, so we need to use a workaround. The simplest and most common is to make a struct containing a single member of the correct type, and passing in the struct pointer.
struct hndlStruct, hndl as short
'Set hndl value to what you need here hndlStruct.hndl.struct = 0
calldll #DrDAQ,"UsbDrDaqOpenUnit", hndlStruct as struct, ret as long
Post by Brandon Parker on Mar 24, 2021 11:04:58 GMT -5
To open the DLL, you need to wrap the name in quotation marks. If the DLL is not in the same directory, you need to provide the full path to the DLL most of the time.
I think you might have to approach the function call like this since the handle parameter is passed to the DLL and returned as an altered value, so it needs to be a pointer which we can accomplish by using a single value structure of the appropriate size. Not knowing the size of the return value (I can't find it in the manual) long would be my guess, but you can adjust it appropriately if you find the definition. You also need to find the enumeration/declaration for the possible PICO_STATUS values that are returned by the various DLL function calls.
Struct drDAQHandle, value As struct
Open "DrDAQ32.DLL" For DLL As #DrDAQ CallDLL #DrDAQ, "UsbDrDaqOpenUnit", drDAQHandle As struct, _ PICO.STATUS As long
'Check whether PICO.STATUS is equal to the defined value of PICO_OK here 'to ensure that the returned value is valid. Print DrDAQHandle.value.struct
If I were writing this for myself, I would encapsulate the DLL function calls into LB functions like so... Struct drDAQHandle, value As struct
Function OpenDrDAQUnit() CallDLL #DrDAQ, "UsbDrDaqOpenUnit", drDAQHandle As struct, _ OpenDrDAQUnit As long
'Check whether OpenDrDAQUnit is equal to the defined value of PICO_OK here 'to ensure that the returned value is valid and do something or leave it 'to the calling code to deal with...functions are awesome...
'Error trapping is also possible and scoped appropriately in functions/subs 'which can help prevent some issues if handled correctly. End Function
Post by Chris Iverson on Mar 24, 2021 13:18:58 GMT -5
The C function declaration he provided specifies "handle" as a pointer to a short(short * handle), not a short(short handle).
Based on the function declaration, I'd say it only returns success or an error code in the return value(hence the return value being declared as PICO_STATUS), and the handle parameter is where the actual handle gets returned(if successful).
Also, to answer your final question, frank:
3) Should I expect that, generally, third party Dlls be accessible to Liberty Basic? If I'm on a hiding to nothing, I might consider writing a program in C which I can call from LB. But it would be good to know.
In general, DLLs with functions with C-style linkage can be used, as long as the datatypes of the functions are accessible in LB. (Most things can be worked with in LB, but there are some DLLs out there now that expect direct 64-bit integers, which LB isn't capable of yet.)
Shared DLL variables can't be used in LB(that is, variables declared as "extern" accessible from wherever the DLL is loaded), and C++ DLLs can't directly be used in LB. (Though for C++ DLLs, you can manually create a C-compatible shim library to access the C++ stuff from LB, though that'll take work to write the code to manually manage the C++ objects.)
These restrictions don't actually exclude as much as you might think; directly sharing full C++ objects/classes in precompiled C++ binary libraries is actually fairly uncommon, due to ABI compatibility issues. (That is, if you have a C-compatible library, pretty much everything on any computer can interface with it in some way, including LB. If you have a C++ DLL, you can ONLY use that DLL if you use the same compiler and compiler version that created the DLL in the first place, because of name mangling issues across compilers and compiler versions. It's basically a big pain unless you go back to the source code and recompile everything yourself using the compiler you want to use for your code.)
There are some things that may make it more difficult to work with a specific library in LB, such as needing to perform weird memory manipulation or datatype stuff, but overall, you generally stand a good chance of being able to use it.