-1

I have a C++ dll which I'm trying to use it in Python,

>>> from ctypes import *
>>> mydll = cdll.LoadLibrary("C:\\TestDll.dll")

until now there are no errors, system seem to be doing what I wanted, but when I try to access mydll, the Intellisence in the Python IDLE shows the following,

enter image description here

from the above pic, it's clear that the intellisence doesn't show up any available functions of the dll, but when I checked the same TestDll.dll with dumpbin /EXPORTS TestDll.dll it has 45 functions, but none of those functions are available with python.

enter image description here

Please Note: There are several questions on this topic, I tried the following suggestions but no use,

Now my question is how do I load all the available functions(as shown by dumpbin)?

Edit 1

Based on eryksun suggestion, I was able to make some progress. The TestDll.dll comes along with a header file TestDll.h(my bad I missed this file earlier), from which I could see the available Exported Functions.

TestDll.h:

_stdcall Function1 (const char* prtFileString, cont char* prtDescrip, struct FileParams* ptrParsms);

struct FileParams
{
  float val1;
  void* pMarker;
};

now I've tried the following,

>>> mydll = CDLL("c:\\TestDll.dll")
>>> Function1 = mydll.Function1
>>> Function1.restype = c_int

until now it's fine, but when I try to define the argTypes, not sure how to do it for structs?

>>> Function1.argtypes = (c_char_c, c_char_c, ???)

any suggestions are much appreciated.

Community
  • 1
  • 1
SanVEE
  • 2,009
  • 5
  • 34
  • 55
  • 1
    Do you have C-wrappers around your C++ functions? See http://stackoverflow.com/questions/10163832/python-simple-ctypes-dll-load-yields-error/10163943#10163943 – Markku K. Feb 03 '15 at 16:44
  • Not sure if that's the case – SanVEE Feb 03 '15 at 16:50
  • 1
    Then you probably don't -- ctypes only works with C. You have to go through some extra steps to use C++. – Markku K. Feb 03 '15 at 16:52
  • yeah I was wrong & I thought ctypes will be able to import all dll's no matter whether it's c or c++, anyways thanks. – SanVEE Feb 03 '15 at 16:56
  • Are the symbol names mangled? If not they were compiled `extern "C"`. – Eryk Sun Feb 03 '15 at 17:26
  • 1
    ctypes won't parse PE image exports as dumpbin does (nor other platforms such as Linux ELF). Load the DLL with `mydll = CDLL("TestDll")`. To instantiate a `_CFuncPtr`, get an exported name as an attribute, e.g. `foo = mydll.foo`, and define the prototype via `foo.restype` and `foo.argtypes`. Or call a prototype (`_CFuncPtr` subclass) with a tuple of a name and lib, e.g. `foo = CFUNCTYPE(c_int, c_char_p)(('foo', mydll))`. On Windows this is implemented via [`GetProcAddress`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx). – Eryk Sun Feb 03 '15 at 17:33
  • @eryksun, thanks for the responce, I dont think the symbol names where mangled, `dumpbin` shows all the names but not sure how they've compiled. As per the suggestion I'm able to load the dll `mydll = CDLL("TestDll")`, but unable to instantiate functions. could you show me an example please? – SanVEE Feb 04 '15 at 10:01
  • 1
    Here's an example. `msvc = CDLL('msvcr100');` `atoi = msvc.atoi; atoi.restype = c_int; atoi.argtypes = (c_char_p,)`. Or instantiate a prototype: `atoi = CFUNCTYPE(c_int, c_char_p)(('atoi', msvc))`. Either way, `assert atoi(b'123') == 123`. – Eryk Sun Feb 04 '15 at 11:15

1 Answers1

2

Based on your header, here's a dummy C file (for Windows) that can be used to test a ctypes wrapper. You mentioned C++ but the example was a C interface, which is a good thing because ctypes works with C functions not C++.

x.c

#include <stdio.h>

struct FileParams
{
  float val1;
  void* pMarker;
};

__declspec(dllexport) _stdcall Function1 (const char* prtFileString, const char* prtDescrip, struct FileParams* ptrParsms)
{
    printf("%s\n%s\n%f %p\n",prtFileString,prtDescrip,ptrParsms->val1,ptrParsms->pMarker);
}

Here's the ctypes wrapper. Note that ctypes does not inspect the DLL and automatically load all the functions. You have to declare the functions, parameters and return values yourself. See ctypes:structures and unions for the Structure syntax.

Also note that for a DLL with _stdcall functions use WinDLL instead of CDLL.

x.py

#!python3
import ctypes

class FileParams(ctypes.Structure):
    _fields_ = [('val1',ctypes.c_float),
                ('pMarker',ctypes.c_void_p)]

    x = ctypes.WinDLL('x')
    x.Function1.argtypes = [ctypes.c_char_p,ctypes.c_char_p,ctypes.POINTER(FileParams)]
    x.Function1.restype = ctypes.c_int
    
    fp = FileParams(1.234,None)
    x.Function1(b'abc',b'def',ctypes.byref(fp))

And the output:

abc
def
1.234000 0000000000000000
Community
  • 1
  • 1
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251