list exported functions from dll with ctypes

2019-03-11 15:34发布

Is there any way to know which functions are exported from the dll through python foreign function library ctypes?

And if possible to know details about the exported functions through ctypes.

If yes, could someone provide a snippet of code?

7条回答
冷血范
2楼-- · 2019-03-11 16:09

@Mark's answer uses Visual Studio tools.

On windows you can also use Dependency Walker to get the function names of dll exports.

Sometimes names are mangled and can't be used as a valid python function name.

You can use getattr to get a handle to mangled functions, e.g:

mylib = ctypes.cdll('mylib.dll')
my_func = getattr(mylib, '_my_func@0')

my_func()
查看更多
Root(大扎)
3楼-- · 2019-03-11 16:10

If you are on Linux, there is a handy utility nm to list the content of a shared library (there is always a handy utility on Linux, especially for C stuff).

Here is the question about it.

You use it with the -D flag: nm -D ./libMyLib.so

查看更多
淡お忘
4楼-- · 2019-03-11 16:12

I don't think ctypes offers this functionality. On Windows with visual studio:

DUMPBIN -EXPORTS XXX.DLL

Or for mingw on windows:

objdump -p XXX.dll
查看更多
\"骚年 ilove
5楼-- · 2019-03-11 16:19

In general, this is not possible, because, again in general, dynamically loaded libraries do not carry the meta-information you require. It may be possible to obtain that information in certain special cases through system-specific ways, but ctypes itself does not fetch that information. You can record such info via ctypes (see e.g. the restype and argtypes attributes of function pointers), but only after you have obtained it by different means.

查看更多
看我几分像从前
6楼-- · 2019-03-11 16:20

YES! there is a very clever native method to do it.

let's say you are using Python ctypes. put something like this in your C code:

1) in your C code:

#define PYEXPORT extern "C" __declspec(dllexport)

now put PYEXPORT above the function you want to export:

PYEXPORT
int myfunc(params){

2) After compiling, go back into Python and open your .c file, and parse it similar to this:

source1_ = open(cfile_name + '.c')
source1 = source1_.read()
source1_.close()
fn = source1.split('PYEXPORT')[-1].split('(')[0].split(' ')[1]

shell input: fn

shell output: 'myfunc'

3) Now here's the clever part: define a new function in a string:

a1 = """
global get_c_fn
def get_c_fn(dll):
     func = dll."""
a2 = """
return func"""
a3 = a1 + fn + a2

print(a3)
global get_c_fn
def get_c_fn(dll):
    func = dll.myfunc
    return func

NOW do exec(a3) and it will turn that string into a function that you can use.

4) do the usual:

mydll = ctypes.CDLL(cfile_name + '.dll')
c_fn = get_cuda_fn(mydll)
c_fn.argtypes =  func_params (an array of C-converted inputs you need)
c_fn( *[params] )

and there you have a python wrapper for a C script without having to modify ten different things every time something changes.

查看更多
等我变得足够好
7楼-- · 2019-03-11 16:24

If you've also got the source for said library, and you're looking for a fully automated all-python way, you could use pycparser

for the file: prog.c

typedef short int ret_t;
typedef short int param_t;

ret_t add(param_t a, param_t b) {
    return (ret_t)(a + b);
}

ret_t passthrough(ret_t (* func)(param_t a, param_t b), param_t a, param_t b) {
    // parameter intentionally altered.
    // if this isn't done, compiler will deem entire function redundant
    return func(a, b + 1);
}

compiling with gcc

gcc -I. -E ./prog.c > prog-preproc.c

gives us the pre-processed c file: prog-preproc.c then in python:

import pycparser
parser = pycparser.c_parser.CParser()

with open('prog-preproc.c', 'r') as fh:
    ast = parser.parse(fh.read())

class FunctionVisitor(pycparser.c_ast.NodeVisitor):
    def visit_FuncDef(self, node):
        print("found function: %s" % node.decl.name)
        #node.show()

FunctionVisitor().visit(ast)

yields

found function: add
found function: passthrough

To dig further you can also get parameter and return types. Uncomment node.show() for more information from within the Abstract Syntax Tree (AST)

I'll be releasing a library for this soon (I'll try to remember to come back and drop a link)

查看更多
登录 后发表回答