Domanda

I've got a C DLL that exposes a handful of methods that return void pointers to a Class like so:

void *GetLicense() {
    static AppLicenseImpl ipds_;
    return (void *) &ipds_;
}

In C++, after loading the DLL, I'd do this to work with it:

typedef void *(* FPGetLicense)();
GetLicense_ = (FPGetLicense)GetAddress("GetLicense");
license_ = (AppLicense *) GetLicense_();
license_->GetApplicationStatus(); // Load data so that other calls don't fail

I can't figure out how to parallel that in Python. This gets me the pointer:

d = ctypes.cdll.LoadLibrary('license.dll')
d.GetLicense.restype = ctypes.c_void_p
p = d.GetLicense() # returns ptr loc, something like 8791433660848L

But I obviously can't call p.GetApplicationStatus() in Python. Does anyone have a suggestion on how I'd instantiate that Class the rest of the way in Python so that I can call GetApplicationStatus()?

È stato utile?

Soluzione 2

I spent more time with this - from c++ when I want to work with the class instance the void pointer refers to I do something like this:

class AppLicense {
public:
    AppLicense() {}
    virtual LicenseStatus GetApplicationStatus() = 0;
}

But I couldn't figure out how to do that in Python. This does not work:

class AppLicense(object):
  def GetApplicationStatus(self):
    pass

So instead I exported another function in the dll like this:

extern "C" {
    int P_GetApplicationStatus(void *ptr) {
        try {
            AppLicenseImpl * ref = reinterpret_cast<AppLicenseImpl *>(ptr);
            return ref->GetApplicationStatus();
        } catch (...) {
            return 0; // License Error default.
        }
    }
}

Once I had that in place, using it from Python is accomplished like this:

d.GetLicense.restype = ctypes.c_void_p
p = d.GetLicense()

d.C_GetApplicationStatus.argtypes = [ctypes.c_void_p]
status = d.P_GetApplicationStatus(p)

Altri suggerimenti

Quoting from the docs:

Sometimes you have instances of incompatible types. In C, you can cast one type into another type. ctypes provides a cast() function which can be used in the same way.

So, the Python equivalent of the C++ code is:

license = cast(d.GetLicense(), ctypes.POINTER(AppLicense))
license.GetApplicationStatus()

However, often this isn't necessary; you may be able to just do this:

d.GetLicense.restype = ctypes.POINTER(AppLicense)

This looks like "cheating", but it really isn't. You're just telling it to call the POINTER(AppLicense) constructor with the result. And since POINTER(AppLicense) is a ctypes data type, it will not have to first assume the result is a C int.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top