0

I'm trying to call a function from dll in python 3.4 with the following signature (more: http://www.lawlabs.ru/parser_address.htm):

function GetAddressFields(
    AddressStr: String;
    var FullStr: String;
    var QualifiedStr: String;
    Separator: ShortString = #13#10;
    IsRussia: Boolean = True;
    WithDescription: Boolean = True;
    WithExceptions: Boolean = True;
    LastIsHome: Boolean = True;
    Subject: Boolean = True;
    WithUnrecognized: Boolean = True): String;

I think syntax is Delphi and get an error when using ctypes for this signature.

My expected match for delphi and ctypes types:

String -> c_char_p  
ShortString -> c_char_p  
var String -> POINTER(c_char_p)  
boolean -> c_bool  

Therefore the function signature in Python (where dll = windll.LoadLibrary(...)):

dll.GetAddressFields.argtypes = (
    c_char_p,
    POINTER (c_char_p),
    POINTER (c_char_p),
    c_char_p,
    c_bool,
    c_bool,
    c_bool,
    c_bool,
    c_bool,
    c_bool)

dll.GetAddressFields.restype = c_char_p    

However, an error occurs with this signature.

Attempt to pass parameters:

param_1 = c_char_p("".encode("ascii"))
param_2 = c_char_p("".encode("ascii"))
result = dll.GetAddressFields(
    c_char_p('test'.encode("ascii")),
    byref(param_1),
    byref(param_2),
    c_char_p("\r\n".encode("ascii")),
    True,
    True,
    True,
    True,
    True,
    True)

The complete error code is:

OSError: exception: access violation reading 0x00000001

Interestingly, when replacing the first boolean parameter with False, we have

OSError error: exception: access violation reading 0x00000000

When you try to pass boolean parameters by reference, an error occurs with random addresses

How solve this problem?

1
  • Can't call that dll from Python Commented Apr 19, 2019 at 22:37

1 Answer 1

2

You are right: that is Delphi (or FreePascal), and that is the problem.

I'm afraid the people who wrote the DLL didn't think about how the DLL could be used by other languages. They export functions with Delphi-specific arguments like string and ShortString, that can only be used by Delphi or C++Builder with the same shared memory manager as the DLL, and not even by all versions of these.

So you won't be able to use the DLL directly, not using C and not using ctypes. String does not map to c_char_p, nor does the different type ShortString, etc. The only type that matches is c_bool, but that won't get you very far.

You could talk to the authors of the DLL and tell them to read my article on how to write a DLL that can be used by other languages too: DLLs dos and don'ts.

Or you could find someone who writes a wrapper for the DLL, either using Delphi or C++Bulder, that wraps the functions and converts the Delphi-specific types to C-compatible types like char * (PAnsiChar) or wchar_t * (PWideChar).

I can't read the page you linked to, so I don't know if you have access to the source code. If so, you could try to find someone who changes the exports so that they are directly usable from C. Then you would not need a wrapper.


FWIW, these types can also be found in FreePascal, but there you'd have the same problem. The solution would be the same, too.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks you. Unfortunately I do not have access to the source code. If the only way remains is to write a wrapper on the Delphi for this library then I will have to go this way. Remember the past :)
Take a look at the imports of the DLL. If it needs a shared memory manager (sharemem.dll or similar, IIRC), use the ShareMem unit as first unit in your wrapper and hope that it is a usable version.

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.