我根据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]
提前致谢
答案 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))