5

I'm using a proprietary library on linux that uses SAFEARRAY type in a callback function:

HRESULT Write(SAFEARRAY *Data)

SAFEARRAY is defined in a header file as typedef void SAFEARRAY.

I must define a callback function that will get the data (eg. as *unsigned char) and it's length (eg. as int or size_t) and write the data somewhere.

Something like:

HRESULT MyWrite(SAFEARRAY *Data) {
  unsigned char *data = SafeArrayGetData(Data);
  size_t length = SafeArrayGetLength(Data);
  write_data_somewhere(data, length);
}

And then use it with the library:

ProprietaryLib::ExportThing(thing, MyWrite);

So my question is: How to get the data and it's length on linux, where I have no oaidl.h or oleauto.h header file.

microo8
  • 3,568
  • 5
  • 37
  • 67
  • `SAFEARRAY Data` I'm pretty sure that a named argument may not be void. – eerorika Jan 24 '19 at 11:18
  • Sorry I forgot the * – microo8 Jan 24 '19 at 11:22
  • 1
    C++ arrays don't store the length anywhere. There's no way to get the length of an arbitrary array. – Barmar Jan 24 '19 at 11:25
  • Does the library provide a way to get the length of the array? – Barmar Jan 24 '19 at 11:26
  • 1
    I cannot get the length of the data with the library. SAFEARRAY is a Microsoft thing and they didn't provide a way to use it in the linux port of the library. – microo8 Jan 24 '19 at 11:29
  • `typedef struct tagSAFEARRAY { USHORT cDims; USHORT fFeatures; ULONG cbElements; ULONG cLocks; PVOID pvData; SAFEARRAYBOUND rgsabound[1]; } SAFEARRAY;` well, `Data->cbElements` is the size of an array in elements. You should rewrite the headers from scratch from the documentation. – KamilCuk Jan 24 '19 at 11:48
  • 2
    Library should provide you functions to extract needed data from SAFEARRAY or header with definition of structure. Do they provide example code? SAFEARRAY is ugly beast https://msdn.microsoft.com/en-us/magazine/mt778923.aspx?f=255&MSPPError=-2147217396 – Frane Jan 24 '19 at 11:49
  • @Frane thanks, that link is great. So I try to implement my own `MYSAFEARRAY` from that definition, then cast the `Data` pointer to `MYSAFEARRAY` and see what's in it. – microo8 Jan 24 '19 at 12:03
  • @KamilCuk when I cast the `Data` pointer to `MYSAFEARRAY` (which is a struct defined as that in your comment), the structure is weird. `cDims` is big (like `60128`).`cbElements` is 0, and `pvData` points to memory that is not owned by the process and fails with segmentation fault if I try to touch it. Any advice? – microo8 Jan 24 '19 at 12:58
  • On MS Windows you need to lock SAFEARRAY before accessing data. That library doesn't seem well ported to linux. Is there any other way to retrieve data besides `ProprietaryLib::ExportThing`? – Frane Jan 24 '19 at 13:10
  • There is just `ProprietaryLib::ExportToFile(thing, filename)` but I wanted to avoid writing and then reading a file. – microo8 Jan 24 '19 at 13:37
  • If you can, try to redefine it in terms of `std::vector`. If you can't, I'll shed a tear for you. – Clearer Jan 28 '19 at 10:05
  • @Clearer just cast it to `std::vector`? – microo8 Jan 28 '19 at 10:23
  • What's the name of this proprietary linux library? Does it support locking/unlocking of the SAFEARRAY? Seems like an odd beast to use in linux. – Ted Lyngmo Jan 29 '19 at 18:27
  • It is the ABBYY FineReader SDK, and to me it appears that it was first written for windows and then somehow automatically ported to linux. These MS types are defined in an header (like the `HRESULT`, `USHORT`, ...) and also `SAFEARRAY` is there as `void` (but an comment above the `SAFEARRAY` definition says `//not supported`). It is a mystery to me, how can they compile on linux the shared lib with `SAFEARRAY` in it, but no definition/implementation of the type exists. – microo8 Jan 30 '19 at 08:18
  • What does the FineReader's SDK documentation say about these callbacks? Have you confirmed that you actually get the calls to the callback function? Perhaps asking (or searching) in [Knowledge Base - ABBYY FineReader Engine 11 for Linux](https://knowledgebase.abbyy.com/?&ProductId=375&version=fbb2edb1-b5a2-4b20-a593-031bf8e8227e&platform=7dc0873a-de9d-4f99-8b6e-7d0e8bc98f10) will be more fruitful. – Ted Lyngmo Jan 30 '19 at 11:52
  • There is nothing in the knowledge base about the interface i'm implementing. And the documentation doesn't talk about what to do with `IFileWriter::Write` and the `SAFEARRAY` argument in linux. It's takes it as if it where the same on all platforms. – microo8 Jan 30 '19 at 12:08
  • Ok, but if you ask a question about how to implement the interface in Linux in that forum, chances are probably greater that you find someone that has first hand experience doing just that. – Ted Lyngmo Jan 30 '19 at 12:58
  • My question is there for 6 days without an answer https://forum.ocrsdk.com/thread/how-to-get-data-from-safearray/ – microo8 Jan 30 '19 at 13:20
  • I see. I would try contacting ABBYY directly in that case. – Ted Lyngmo Jan 30 '19 at 16:15

1 Answers1

0

Two thoughts on the matter:

konst
  • 336
  • 2
  • 4
  • I've seen the Wine `SAFEARRAY` implementation, but without the correct structure it will not work. `pvData` points to not allocated memory and `cbElements` is always 0. Also tried to write the bytes to binary file and then inspect it with a hex editor, but there is hard to find a pattern. Now i'm experimenting with gcc's `-fpack-struct=8` and `__attribute__((aligned(8))` with no success. Also it is interesting that the fist bytes are an pointer to somewhere. When I do `struct S { void *p} *x =(struct S)Data`, I can read the value in `*x->p`. – microo8 Feb 01 '19 at 07:24