frank
New Member
Posts: 1
|
Post by frank on Mar 24, 2021 4:47:06 GMT -5
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
|
|
|
Post by Rod on Mar 24, 2021 9:36:15 GMT -5
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
Close #DrDAQ
If I were writing this for myself, I would encapsulate the DLL function calls into LB functions like so...
Struct drDAQHandle, value As struct
Print OpenDrDAQUnit()
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
{:0)
Brandon Parker
|
|
|
Post by Brandon Parker on Mar 24, 2021 11:22:20 GMT -5
Well, Chris beat me to it...
{:0)
Brandon Parker
|
|
|
Post by Rod on Mar 24, 2021 13:04:14 GMT -5
Not sure the device id is a pointer as we are just initiating the device. It is not returning a handle either. I know we will need structs later when we gather info from the device.
Usually the initiation command for such divices simply passes the port number or device id and returns success.
|
|
|
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:
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.
|
|
|
Post by Brandon Parker on Mar 24, 2021 13:32:45 GMT -5
It's definitely a pointer ... It is passed and returned according to the documentation. The function's return value is simply a success or failure value. The manual can be found here... {:0) Brandon Parker
|
|