2

I have a C dll that returns a PDF file as a unsigned char* containing hex values. How do I use ctypes to retrieve this array and save it to a file 'unearthing' the PDF?

For example in C I do this:

unsigned char* manual = getPluginManualAsPDF(mPlugin);
long nrOfBytes        = getPluginManualNrOfBytes(mPlugin);

string tempFile(mtk::JoinPath(getTempFolder(getRRHandleFromPlugin(mPlugin)), "AddNoisePluginDoc.pdf"));
ofstream temp(tempFile.c_str(), std::ios::binary);

long byteNr = 0;
while (byteNr < nrOfBytes)
{
    temp<< manual[byteNr];
    byteNr++;
}

temp.close();

    //Spanw an external pdf reader
    ShellExecute(Handle, "open", tempFile.c_str(), NULL, NULL,SW_SHOWNORMAL) ;
}

I am trying to access the same functions (getPluginManualAsPDF and getPluginManualNrOfBytes) via CTypes, i.e.

rrpLib.getPluginManualAsPDF.restype = c_buffer
def getPluginManualAsPDF(pluginHandle):
    return rrpLib.getPluginManualAsPDF(pluginHandle)

def getPluginManualNrOfBytes(pluginHandle):
    return rrpLib.getPluginManualNrOfBytes(pluginHandle)

But have problem with the return of getPluginManualAsPDF() function.. Any help appreciated.

3
  • May as well swap C++ into that tag list, since you're, you know, using it and all. Commented Nov 18, 2013 at 18:58
  • So, you have to call two functions, One to get the pointer to the data, the other to get the length of that data? That's pretty unusual... Commented Nov 18, 2013 at 19:31
  • That is C. The getPluginManualAsPDF returns a unsigned char* containing the bytes. The client need to know how many bytes there are in the array, that is why the second function is there. Commented Nov 18, 2013 at 19:42

1 Answer 1

1

Assuming your getPluginManualAsPDF and getPluginManualNrOfBytes have the following prototype:

/* FIXME: the type of `mPlugin` isn't clear, is it void * ? */

unsigned char * getPluginManualAsPDF(void *mPlugin) {
  static unsigned char manual[] = {1, 2, 3};
  return manual;
}

long getPluginManualNrOfBytes(void *mPlugin) {
  return 12345;
}

you can call these two functions using:

from ctypes import *

rrpLib = cdll.rrpLib # or windll if it use STDCALL

getPluginManualAsPDF = rrpLib.getPluginManualAsPDF
getPluginManualAsPDF.restype = POINTER(c_ubyte)
getPluginManualAsPDF.argtypes = [c_void_p]

getPluginManualNrOfBytes = rrpLib.getPluginManualNrOfBytes
getPluginManualNrOfBytes.restype = c_long
getPluginManualNrOfBytes.argtypes = [c_void_p]

for example:

# gcc -Wall rrpLib.c -shared -o rrpLib.dll
# python
>>> from ctypes import *
>>>
>>> rrpLib = cdll.rrpLib # or windll if it uses STDCALL
>>>
>>> getPluginManualAsPDF = rrpLib.getPluginManualAsPDF
>>> getPluginManualAsPDF.restype = POINTER(c_ubyte)
>>> getPluginManualAsPDF.argtypes = [c_void_p]
>>>
>>> getPluginManualNrOfBytes = rrpLib.getPluginManualNrOfBytes
>>> getPluginManualNrOfBytes.restype = c_long
>>> getPluginManualNrOfBytes.argtypes = [c_void_p]
>>>
>>> getPluginManualAsPDF(None)[0]
1
>>> getPluginManualAsPDF(None)[1]
2
>>> getPluginManualAsPDF(None)[2]
3
>>>
>>>
>>> ptr = getPluginManualAsPDF(None)
>>> manual = cast(ptr, POINTER(c_ubyte * 3))[0]
>>> manual
<__main__.c_ubyte_Array_3 object at 0x017801C0>
>>> open('out.txt', 'wb').write(bytearray(manual))
>>> open('out.txt').read()
'\x01\x02\x03'
>>>
>>>
>>> getPluginManualNrOfBytes(None)
12345
>>>
Sign up to request clarification or add additional context in comments.

2 Comments

You should cast the result as an array, e.g. manual = cast(ptr, POINTER(c_char * nrOfBytes))[0]. This supports the buffer protocol to efficiently write the buffer allocated by the library to a file. It can be passed directly to the write method.
Great. I got this figured out with your suggestions. Key was the POINTER(c_ubyte) and then do the cast, as suggested. I could then save the 'manual' as this: with open(outFName, 'wb') as output: output.write(manual) (And Yes, the pluginHandle is void* )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.