Python ctypes识别dll函数结果

时间:2014-11-04 20:59:00

标签: python windows dll ctypes

我根据DLL的文档提供了一些功能(还有更多):

# there are 2 lines in the other example like this
# define CALLTYPE __stdcall
# define pLSenvL void*

pLSenvL CALLTYPE LScreateEnvL()
int LSopenLogFileL( pLSenvL pL, char *pcLogFile)
int CALLTYPE LSsetPointerL(pLSenvL pL, double* pdPointer, int* pnPointersNow)
int LSexecuteScriptL( pLSenvL pL, char* pcScript)
int LScloseLogFileL( pLSenvL pL)
void LSclearPointers( pLSenvL pL)

到目前为止,我所做的是:

from ctypes import *

api = CDLL("PATH_TO_DLL")
pLEnv = api.LScreateEnvL()
script = "STRING FULL OF COMMANDS"

print api.LSexecuteScriptL(pLEnv, script)

它有效,但现在我要复制一个我发现的例子:

void CSDlg::OnSolve()
{
  int nError, nPointersNow;

  CString csScript, cs;
  double dNeeds[1], dStart[1];

  dNeeds[ 0] = (double) nNeedsM;

  pLSenvL pL;
  pL = LScreateEnvL();

  nError = LSopenLogFileL( pL, "log_file.log");
  nError = LSsetPointerL( pL, dNeeds, &nPointersNow);
  nError = LSsetPointerL( pL, dStart, &nPointersNow);

  csScript = "SET ECHOIN 1\n";

  // Run the script
  nError = LSexecuteScriptL( pL, (LPCTSTR) csScript);
  // Close the log file 
  LScloseLogFileL( pL);
  csStartM.Format( "%d", (int) dStart[0]);
}

到目前为止,我已经这样做了:

nError = c_int
nPointersNow = c_int

dNeeds = c_double()
#I'm just setting a random value
dNeeds = [c_double(10)]

pLEnv = api.LScreateEnvL()
nError = api.LSopenLogFileL(pLEnv, "log_file.log")
# here I got 
# Procedure called with not enough arguments (8 bytes missing) or wrong calling convention
nError = api.LSsetPointerL(pLEnv, byref(dNeeds), nPointersNow)
# and here I got
# byref argument must be a ctypes instance, not 'list'

所以我搜索过,我必须做这样的事情

#now here comes my problem
#according to documentation it is
#  int CALLTYPE LSsetPointerL(pLSenvL pL, double* pdPointer, int* pnPointersNow)
api.LSsetPointerL.restype = c_int
api.LSsetPointerL.argtypes = [ ¿?, c_double, c_int]
  • 什么应该作为argtypes数组中的第一个元素?
  • 我有什么需要担心的CALLTYPE定义吗?

提前致谢

1 个答案:

答案 0 :(得分:0)

Procedure called with not enough arguments (8 bytes missing) or wrong calling convention”指的是你如何调用DLL。您使用了CDLL,但它显示“# define CALLTYPE __stdcall”,因此您应该使用WinDLL(see ctypes docs)。这有时可以正常工作,但似乎在更复杂的电话上失败了。

您没有实例化nPointersNow,您可能意味着nPointersNow()

您无法将dNeeds设置为列表。也许你的意思是:

somefunc.argtypes = [c_double()]
dNeeds = c_double(10)
nError = api.LSsetPointerL(pLEnv, byref(dNeeds), nPointersNow)

类型plSenvL应该在您的文档中的某个位置定义。 LScreateEnvL返回该类型,如下所示:

pLSenvL CALLTYPE LScreateEnvL()
pLSenvL __stdcall LScreateEnvL() (<- what the above line really means)

所以你需要知道它是什么。我们可以猜测它是一个名为LSenvL的指针(一个整数),你可能需要为它做一个结构。不难,但你需要知道它是如何定义的。也就是说,你可以避免它,因为第一个函数返回它。因此,如果您不需要直接使用它,您可以尝试像这样狡猾:

LScreateEnvL = api.LScreateEnvL
LScreateEnvL.restype = c_int   # just assume it's an int

LSopenLogFileL = api.LSopenLogFileL
LSopenLogFileL.restype = c_int
LSopenLogFileL.argtypes = (c_int,   # again just assume
                           c_char_p)

LSsetPointerL = api.LSsetPointerL
LSsetPointerL.restype = c_int
LSsetPointerL.argtypes = (c_int,   # assume int
                          POINTER(c_double),
                          POINTER(c_int))

pLSenvL = LScreateEnvL()

dPointer = c_double()
nPointersNow = c_int()
nError = LSsetPointerL(pLSenvL,
                       byref(dPointer),
                       byref(nPointersNow))