Chinaunix

标题: python调用DLL问题(急) [打印本页]

作者: Heaice    时间: 2009-01-05 17:14
标题: python调用DLL问题(急)
test.DLL中封装了几个函数
int A()
int B(int Handle, ref long Len_s1, ref long Len_s2)

其中,Handle是调用A后得到的句柄,需要传入到B中

python实现:

import cytpes

#加载DLL

tt=ctypes.CDLL('C:\\Python26\\test.dll')

s1=A();
ss=ctypes.c_int()
ssd=ctypes.c_int()
s2=B(s1,ctypes.byref(ss),ctypes.byref(ssd))

从s2的返回值来看,调用是成功的,但是ss,和ssd的值始终为零,请各位大虾帮帮忙看看是什么问题

[ 本帖最后由 Heaice 于 2009-1-5 17:21 编辑 ]
作者: luffy.deng    时间: 2009-01-05 18:13
ref long Len_s1, ref long Len_s2这是什么意思?
作者: Heaice    时间: 2009-01-05 23:07
原帖由 luffy.deng 于 2009-1-5 18:13 发表
ref long Len_s1, ref long Len_s2这是什么意思?



这个好像是C++中得吧~
应该是指出该参数是一个对象得引用
ref long Len_s1, ref long Len_s2就是说,Len_s1,Len_s2是一个long型的引用,可以这么理解~

其实,这两个参数的值是由该函数处理后,需要在外面其他地方使用的
作者: luffy.deng    时间: 2009-01-06 08:35
ss    ssd 你也没赋值啊。你赋个值试试 比如。
ss=ctypes.c_int()
ss=15

[ 本帖最后由 luffy.deng 于 2009-1-6 08:40 编辑 ]
作者: Heaice    时间: 2009-01-06 09:20
原帖由 luffy.deng 于 2009-1-6 08:35 发表
ss    ssd 你也没赋值啊。你赋个值试试 比如。
ss=ctypes.c_int()
ss=15



ss和ssd的赋值也只能是 ss=ctypes.c_int(10),ssd=ctypes.c_int(20)这样赋值,否则,ss和ssd就不是ctypes类型了

即使对ss和ssd进行赋值后,执行B函数后,ss和ssd的值还是零。



是不是对C++的DLL库,ctypes不支持活着不能使用,而ctypes只能用于C的DLL库,昨天在查找的时候,看到有人这么说,但不确定是否正确

[ 本帖最后由 Heaice 于 2009-1-6 09:27 编辑 ]
作者: luffy.deng    时间: 2009-01-06 09:42
ss.value=15这样也是可行的。能不能给一个test.dll?
作者: Heaice    时间: 2009-01-06 10:41
原帖由 luffy.deng 于 2009-1-6 09:42 发表
ss.value=15这样也是可行的。能不能给一个test.dll?



真实的dll,因某些原因可能无法提供了~

不过,我可以说明我使用该DLL的部分功能,你可以尝试自己创建一个试试

该DLL调用底层驱动程序,获得磁盘在一定时间内的读写文件的字节数,并在B函数中返回


而上述的ss以及ssd就是返回的字节数

[ 本帖最后由 Heaice 于 2009-1-6 10:44 编辑 ]
作者: luffy.deng    时间: 2009-01-06 11:14
c++不会
作者: newrain    时间: 2009-01-06 11:20
test.DLL中封装了几个函数
int A()
int B(int Handle, ref long Len_s1, ref long Len_s2)

python中调用
from ctypes import *

test = CDLL("test")

A = test.A
A.restype = c_int

B = test.B
B.restype = c_int
B.argtypes = [c_int, c_void_p, c_void_p]

#然后通过引用来调用
va1 = 0
va2 = 0
s2 = B( A(), byref(va1), bref(va2) )
作者: Heaice    时间: 2009-01-06 11:37
原帖由 newrain 于 2009-1-6 11:20 发表
va1 = 0
va2 = 0

...



其中
va1,va2得赋值应该是va1=ctypes.c_int(),va2=ctypes.c_int()

但是执行完B函数后,va1和va2得值还是零

[ 本帖最后由 Heaice 于 2009-1-6 12:19 编辑 ]
作者: luffy.deng    时间: 2009-01-06 13:10
是B的确没有改变va1,va2的值,还是不能用c++ 的dll?我用一个c的dll试了一下可以

import ctypes
tt=ctypes.CDLL('add.dll')
g1 = ctypes.c_int(10)
g2 =  ctypes.c_int(15)
print g1,g2
tt.lkadd(ctypes.byref(g1),ctypes.byref(g2))
print g1,g2

输出:
c_long(10) c_long(15)
c_long(500) c_long(510)
作者: Heaice    时间: 2009-01-06 14:02
原帖由 luffy.deng 于 2009-1-6 13:10 发表
是B的确没有改变va1,va2的值,还是不能用c++ 的dll?我用一个c的dll试了一下可以

import ctypes
tt=ctypes.CDLL('add.dll')
g1 = ctypes.c_int(10)
g2 =  ctypes.c_int(15)
print g1,g2
tt.lkadd(ctypes ...



不清楚是否是ctypes对C++不支持。

我确定了下我使用的DLL是使用C写的,B函数(Int B (int Handle, ref long Len_s1, ref long Len_s2))的那种写法是因为有一个C#的程序需要调用,而且好像C#对引用的要求是否是这个样子就不清楚了。

因为我使用的DLL是需要调用底层驱动获得Len_s1,Len_s2的值并通过B函数传出来的,从目前情况来看,好像是python这边没有什么问题,是不是在Python调用时,造成DLL根本就没有调用底层驱动,所以才导致Len_s1,Len_s2始终为零?

唉~被这个搞的都有点崩溃了的感觉

[ 本帖最后由 Heaice 于 2009-1-6 14:03 编辑 ]
作者: luffy.deng    时间: 2009-01-06 14:10
原帖由 Heaice 于 2009-1-6 14:02 发表



不清楚是否是ctypes对C++不支持。

我确定了下我使用的DLL是使用C写的,B函数(Int B (int Handle, ref long Len_s1, ref long Len_s2))的那种写法是因为有一个C#的程序需要调用,而且好像C#对引用的要 ...

可以考虑一下是不是函数B就没有对va1,va2进行修改。可以查一下B的返回值

[ 本帖最后由 luffy.deng 于 2009-1-6 14:13 编辑 ]
作者: Heaice    时间: 2009-01-06 14:32
原帖由 luffy.deng 于 2009-1-6 14:10 发表

可以考虑一下是不是函数B就没有对va1,va2进行修改。可以查一下B的返回值



从调用函数B的返回值为来看,确实是取到了va1,va2。

但是不清楚为啥就成这个样子了,本来以为是python这边的问题,现在看来好像又不是

看来得从DLL这边下手瞧瞧了。


另外,想问下,不知道网络上有没有python实现取得一定时间内磁盘读写文件大小的代码活着是实现方法?

[ 本帖最后由 Heaice 于 2009-1-6 14:35 编辑 ]
作者: luffy.deng    时间: 2009-01-06 19:29
不知道你要干什么用。调用sar能不能得到?
作者: Heaice    时间: 2009-01-07 10:12
原帖由 luffy.deng 于 2009-1-6 19:29 发表
不知道你要干什么用。调用sar能不能得到?



sar是python的一个库还是什么?

那里可以找到?虽然目前不清楚是否能够满足要求,但是可以尝试下
作者: luffy.deng    时间: 2009-01-07 10:15
sar是linux下的命令,用于系统监控,一般都自带了。主页在http://pagesperso-orange.fr/sebastien.godard/download.html

[ 本帖最后由 luffy.deng 于 2009-1-7 10:17 编辑 ]
作者: newrain    时间: 2009-01-07 10:30
#! /usr/env/python
from ctypes import *
test = CDLL("testdll"
A = test.A
A.restype = c_int
B = test.B
B.restype = c_int
B.argtypes = [c_int, c_void_p, c_void_p]
va1 = c_int()
va2 = c_int()

s2 = B(A(), byref(va1), byref(va2) )
print s2, va1, va2


// 测试dll的头文件
#ifndef  TEST_DLL_H
#define  TEST_DLL_H
#define DLLPORT __declspec(dllexport)
extern "C" DLLPORT int A();
extern "C" DLLPORT int B(int handle, int *s1, int* s2);
#endif

// 测试dll的实现文件
#include "testdll.h"
int A()
{
return 1;
}
int B(int handle, int *s1, int* s2)
{
*s1 = 76;
*s2 = 88;
return handle;
}

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
      )
{
    return TRUE;
}


# 输出结果:
1 c_long(76) c_long(8

因此,你应该仔细查看你的dll返回值是否正确,而不是去判断python的代码是否有问题!
作者: Heaice    时间: 2009-01-07 11:40
在这里衷心感谢luffy.deng和newrain 的热心帮助。

原帖由 luffy.deng 于 2009-1-7 10:15 发表
sar是linux下的命令,用于系统监控,一般都自带了。主页在http://pagesperso-orange.fr/sebastien.godard/download.html



我是应用在windows系统下,所以,就只能另寻它法了。

原帖由 newrain 于 2009-1-7 10:30 发表
#! /usr/env/python
from ctypes import *
test = CDLL("testdll")
A = test.A
A.restype = c_int
B = test.B
B.restype = c_int
B.argtypes = [c_int, c_void_p, c_void_p]
va1 = c_int()
va2 = c_in ...

# 输出结果:
1 c_long(76) c_long(8

因此,你应该仔细查看你的dll返回值是否正确,而不是去判断python的代码是否有问题!



因为学习python时间比较短,并且第一次使用python调用DLL,再加上该DLL在另一个程序中使用正常,所以,就以为是python代码那里出现了问题所导致。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2