[Gambas-user] Working with .so library

ML d4t4full at ...626...
Thu Jun 15 14:13:21 CEST 2017


On 15/06/17 08:48, Admin wrote:
> 15.06.2017 17:54, Admin пишет:
>> 15.06.2017 16:19, Tobias Boege пишет:
>>>> All your help was very important for me, I now have completed my cash
>>>> register software to the point where it does everything my company
>>>> needs. I
>>>> must say Gambas is a great language, it's very easy to learn from
>>>> scratch,
>>>> I'm surprised how obvious everything is. But there is a lot of work
>>>> for me
>>>> left to do mostly in terms of managing wrong human actions. My
>>>> software
>>>> works good if the employee doesn't do any mistakes, but that's
>>>> unrealistic,
>>>> so there's a lot of things I want to control and check. And that's
>>>> where I'm
>>>> stuck.
>>>> This library (which still calls itself a driver) theoretically is
>>>> able to
>>>> return a lot of values that I need, but I can't understand basic
>>>> rules of
>>>> how do we take output from a C-lib in Gambas.
>>>> From http://gambaswiki.org/wiki/howto/extern I understood that I
>>>> need to
>>>> locate a space in memory and pass a pointer to a library so that it
>>>> can
>>>> write data into that place in ram, which I would then read and set
>>>> free.
>>>> So I have to declare a pointer, then Alloc(8) it, then pass it to
>>>> my library
>>>> and then read from it like it is a stream. Does this principle
>>>> still work in
>>>> current version of Gambas?
>>> If you do Alloc(8), then you get 8 bytes of memory. You most likely
>>> *don't*
>>> want to read that like a stream, but use Integer@() or similar
>>> functions.
>>>> What I don't understand is how I construct the code in my
>>>> particular case.
>>>> To make an interface to the library I declare external pointer like
>>>> this:
>>>>      Extern CreateFptrInterface(ver As Integer) As Pointer
>>>> Then I declare some pointers that I'll use with help of the
>>>> interface I
>>>> created:
>>>>      Extern put_DeviceEnable(p as Pointer, mode as Integer)
>>>>      Extern GetStatus(p as Pointer, StatRequest as String)
>>>> Then I declare the pointer which will be that interface:
>>>>      Public kkmDrv as Pointer
>>>> So then in sub I can do
>>>> kkmDrv = CreateFptrInterface(12) ' this establishes the interface
>>>> put_DeviceEnabled(kkmDrv, 1) ' this transfers the comand to the
>>>> library
>>>> through the interface.
>>>> And it works great.
>>>> But then If I want to get some data from the library, as I
>>>> understand, I
>>>> have to declare another pointer, allocate ram for it and pass my
>>>> request.
>>>> I don't understand how should I pass that pointer to GetStatus()
>>>> while also
>>>> passing my interface pointer to it, let alone reading data back.
>>>> Totally
>>>> confused.
>>>>
>>> This entirely depends on how the C functions in your library are
>>> declared.
>>> I don't know about your specific library but commonly the occurence
>>> of an
>>> error is indicated by an integer return code, e.g. this might be the
>>> signature of one of the functions in your library:
>>>    int myfunction(void *interface, int argument)
>>> If the documentation says that the return value (int) of this function
>>> indicates an error, then you just need to get that return value back
>>> into
>>> your Gambas program, which you accomplish by declaring the function in
>>> Gambas as
>>>    Extern myfunction(interface As Pointer, argument As Integer) As
>>> Integer
>>> (notice the trailing "As Integer"). Then you can use "myfunction" in
>>> your
>>> Gambas code like any other function and get and interpret its return
>>> value.
>>> So, if this convention for error reporting is used, it is much
>>> simpler to
>>> get information about errors, without using Alloc() and co. Your
>>> library
>>> may use a different convention which actually involves pointers, but
>>> I wouldn't know.
>>> Regards,
>>> Tobi
>>>
>> I should've said it in the beginning. Ofcourse any function returns
>> integer value of 0 as success or -1 as error, but that only indicates
>> that function was successfully executed or not. So GetStatus() will
>> always return 0 because it shurely ran, nothing can go wrong here.
>> But that's not the result I want. GetStatus() actually gives back a
>> string with the status I asked for. Not that I fully understand how
>> it does that. I already gave links to the libfptr.so library itself
>> (http://allunix.ru/back/atol.tar.gz) and it's header files
>> (http://allunix.ru/back/atol-header.tar.gz) so that it's clearer,
>> what I'm talking about, unfortunately I am absolute zero in C to
>> figure things out myself.
>> For example I can see that to get serial number of the device driven
>> by that library i can use a function described like this:
>> get_SerialNumber(void *ptr, wchar_t *bfr, int bfrSize);
>> As far as I can tell what it does is it gets data needed and puts it
>> into some buffer. The result of executing this function through
>> put_SerialNumber(kkmDrv) will always be returned to me as 0.
>> So to see what's in that buffer, I have to then invoke
>> GetStatus(kkmDrv) describe in .h file like GetStatus(void *ptr); and
>> the integer result of this operation will also always be 0, which
>> means that GetStatus itself ran successfully, but I don't care about
>> that, I want to see what it actually told me, not that if it told me
>> it successfully or not. So that's the main confusion. If all this is
>> too complicated and lamely explained then nevermind, I expect it to
>> be so and I'm sorry, that's the best I can do. I'm just really
>> confused that I recieve two answers, one boolean telling if function
>> successfully invoked and one string, carrying the actual data I want.
>> Best Regards,
>> Dmitry.
> UPD: you know, I can be fundamentally wrong about all this library's
> functionality. Maybe it does not give me any data afterall, I'm
> beginning to think that this integer (or rather boolean) value is all
> it gives me back, and the "real" data is just written into it's log
> file. Which is sufficient to me, so, I guess, nevermind. Sorry about
> wasting your time.
> Best regards,
> Dmitry.
Dmitry,
With a desription such as get_SerialNumber(void *ptr, wchar_t *bfr, int
bfrSize); and having reviewed your communications, I would guess that:
  *ptr is a pointer to the interface (an input parameter),
  *buf is a pointer to a -possibly predefined- buffer that the function
will fill with data (the serial number in this case, could call this an
output parameter), and
  bfrSize can be sort of an input/output parameter. bfrSize can hold the
size in wchar_t units in input and the function may alter it to reflect
the actual string size returned in *buf.
All this is just guesswork of course, nothing solid; the actual proper
usage of the function should be not in the header files, but in the
documentation.
The way I would use this call is as follows:
1- Get an interface pointer, let's call it ptrItf. You know how.
2- Get an int or boolean for the function return value, let's call it
retVal.
3- Get a Gambas string filled with CHR(0), and a pointer to its data
(make the string big enough so that a serial number would fit, even in
non-ANSI strings such as UTF-8, and add some slack just to be sure),
let's call that pointer ptrBuf.
4- Get the lenght of the above buffer string, let's call that bufLen.
5- Call the function:
  retVal = get_SerialNumber(ptrItf, ptrBuf, bufLen - 1)
6- If retVal <> 0, increment (double) the string size and retry from 3.
Not in a forever-loop, just once.
7- If retVal = 0 then the serial number should somehow be in the string.
Maybe you have to convert between ANSI/UTF-8/etc., but it should be there.
Please note that the above is, again, guesswork. Not sure of anything.
HTH,
zxMarce.





More information about the User mailing list