[Gambas-user] Working with .so library

Admin admin at ...3661...
Wed May 31 06:48:53 CEST 2017


So, I am writing a programm for my business that would basically be a 
cash register. Don't know for other countries but here in Russia the tax 
law works like this: you have to form a check for a customer in a 
spicific way spicified by the law, so some hardware manufacturers are 
making certified cash registers/check printers that simply form the 
check needed and automatically send tax info to authorities, very simple 
and easy to integrate with ERP systems. The only problem is that most of 
accounting software that is compatible with those registers is written 
for Windows. Now that Windows becomes more and more monstrous, many 
businesses turn to Linux, at least on those computers that are only a 
cashier's workstation that does not need to do much in terms of 
performance power. But the problem is, there's only one or two cashier's 
programms for linux exist for now, that are compatible with that 
certified hardware, and it's not open source or free.


First of all I want to make my own for myself, and second - I want to 
share it. Gambas is a great language in this case because of many 
aspects. In small buisnesses usually there are not a lot of qualified 
programmers to make some apps in C or C++, but instead there usually is 
just a single sysadmin, who is servicing the IT stuff wich usually is 
just one or two PCs and a router/switch. So, Gambas is much more 
accessible to those people as I see it. Programs written on it are easy 
to understand and modify to the needs of a small business.


And what is great - the manufacturers of that certified hardware are 
willing to help: ofcourse they mostly do business with Windows stuff, 
they only work directly with big businesses and they don't produce 
accounting software themselves, but they are kind enough to provide at 
least a binary libraries (they call those - drivers, but i'm not shure 
if it's technically correct) for their hardware even for Linux as a x86 
and x64 .so files. What those binary libraries do is simple conversion 
of easy commands to hex codes that are then passed to a hardware via USB 
or RS232 or Ethernet. It is MUCH easier to work with those commands then 
implement the whole communication protocol from scratch. Ofcourse I am 
not the only one who is interested in those devices to work under linux, 
and as I can tell from different forums in the internet - programmers 
successfully use this libraries and thank the developers. There's not a 
lot of documentation out there, but yeah, on paper it seems to be simple 
enough... if you write your code in C or C++.


Things get much different when you try to use the library in Gambas. 
What I was able to understand from the documentation is that you need to 
"initialize the interface" with the library, which will create a 
"virtual class" and than you can pass your data to it. So, in C (using 
QT) that would look something like this:


  typedef IFptr * (*_CreateFptrInterface)(int ver);

     bool init() {
         QLibrary *lib = new QLibrary("fptr");
         lib->load();
         if(lib->isLoaded()) {
             _CreateFptrInterface CreateFptrInterface = 
(_CreateFptrInterface)lib->resolve("CreateFptrInterface");
             if(CreateFptrInterface) {
                 IFptr * iface = CreateFptrInterface(12);
                 iface->put_DeviceEnabled(true);
                 int result = 0;
                 iface->get_ResultCode(&result);
                 qDebug() << result;
                 wchar_t bfr[1000];
                 int length = iface->get_ResultDescription(bfr,1000);
                 qDebug() << QString::fromWCharArray(bfr,length);
             }
         }
     }


So, as I understand we create a pointer called IFptr by calling 
CreateFptrInterface() and then we pass any other pointer through this 
one. Pardon my terminology, I am new to this stuff.

I wrote some simple code that basically initializes this driver just so 
I can see some output in the driver logs which are kindly created in 
~/.atol. It also sends some data to driver which must change just one 
setting:

-----

Library "~/ATOL/linux-x64/libfptr"

Extern CreateFptrInterface(ver As Integer) As Pointer
Extern put_DeviceSingleSettingAsInt(p As Pointer, s1 As String, s2 As 
Integer) As Integer
Extern ApplySingleSettings(p As Pointer) As Pointer

[...]

Public Sub Button1_Click()
Dim IFptr As Pointer

IFptr = CreateFptrInterface(12)
put_DeviceSingleSettingAsInt(IFptr, "Model", 63)

ApplySingleSettings(IFptr)

End

-----

When I click Button1, the driver surely initializes, I see in logs that 
IFptr object is created. If I provide the wrong version in 
CreateFptrInterface it fails, saying in logs that there's missmatch in 
interface version, so no doubt the argument is passed correctly. I also 
can see that put_DeviceSingleSetting is being called, but the 
configuration does not actually change. The commercial software that 
uses this very same driver and works fine - leaves mostly the same trace 
in driver's log except that I see what arguments are passed to 
DeviceSingleSetting. And in my case I only see that the procedure is 
envoked but with no arguments. I was trying to use many other procedures 
(or methods, or pointers, or what are they?) with the same effect - they 
surely are called and executed, but I can't pass any arguments to them. 
I was experimenting with variable types I send them, and if I, for 
example, send an integer as an argument when the library expects a 
string - it crashes. If I do not use IFptr pointer - it crashes. So I 
think I figured out the syntax correctly, but I still can't get the 
desired result.


My question is basically this: Should I continue experimenting, or is it 
simply impossible to work with this kind of library from Gambas?


Here is the link to the library and some other libraries it uses itself: 
http://allunix.ru/back/atol.tar.gz - there's also a binary executable 
that is a test program, unfortunately it's in Russian, but it still 
shows what logs must look like when everything is correct, just for a 
comparison.


There's simple experiment you can make: it has a pointer 
ShowProperties() which must show a window with driver's settings using 
it's own library libgui_engine.so. When I call ShowProperties(IFptr) it 
prints to log that it can't find this lib, which is expectable, because 
first I must provide the path to it using 
put_DeviceSingleSettingAsBuff(IFptr, "SearchDir", 
"/home/bocha/ATOL/linux-x64/") and AplySingleSettings(IFptr), but when I 
pass this setting, I, as always, see that it passes no arguments, so the 
result stays the same.

I do understand that I ask a lot of invovement, there's no simple way to 
understand what's needed to be done to make this whole thing work so not 
many people would even read this message to the end, but I still hope 
for some answers, they would be much appriciated. Thank you!

Best Regards.

Dmitry Bachilo.





More information about the User mailing list