2014-11-18 8 views
5

Sto provando a inizializzare il Matlab compiler Runtime (MCR) da python usando ctypes. Il mio obiettivo finale è quello di essere in grado di utilizzare una DLL C creata dal compilatore Matlab in python, ma il primo ostacolo che ho bisogno di superare è ottenere MCR attivo e funzionante.Ctypes Python: come passare NULL come argomento con format const char **

Sto usando Python 2.7.8, Matlab 2013a, MCR8.1.

snipit da mclbase.h per mostrare gli argomenti ecc

LIBMWMCLBASE_API_EXTERN_C bool mclInitializeApplication(const char** options, size_t count); 

C equivalente di quello che sto cercando di fare

mclInitializeApplication(NULL,0) 

Ecco i miei vari tentativi di chiamare la funzione in Python. Risultano inevitabilmente in TypeErrors o Windows Error 0xE06D7363. Non posso romperlo! Sono un principiante di Python quindi potrebbe esserci qualcosa di semplice che mi manca. Qualsiasi commento benvenuto!

# Initialize the MATLAB Compiler Runtime global state 
from ctypes import * 

libmcr=cdll.mclmcrrt8_1 

# Load mclbase library 
mcr_dll = cdll.LoadLibrary('C:\\Program Files\\MATLAB\\MATLAB Compiler Runtime\\v81\\bin\\win64\\mclbase.dll') 

# Pick function we want to use 
mclInit=mcr_dll.mclInitializeApplication 

# Set up argument and results types 
mclInit.argtypes = [POINTER(POINTER(c_char)),c_size_t] 
# mclInit.argtypes = [POINTER(c_char_p),c_size_t] #different formatting attempt 
mclInit.restype = c_bool 

a=None 
acast=cast(a,POINTER(c_char_p)) 
acast1=cast(a,POINTER(c_char)) 
acast2=cast(a,POINTER(POINTER(c_char))) 

print 'a=' 
print a 
print 'acast=' 
print acast 
print 'acast1=' 
print acast1 
print '' 

# Try calling the function with various argument types 
try: 
    b=mclInit(None,0) 
except Exception as ex: 
    print ex 
    raw_input("Exception occurred. b=mclInit(None,0) didn't work. Press Enter to continue") 
    print '' 

try: 
    b=mclInit(byref(acast),0) 
except Exception as ex: 
    print ex 
    raw_input("b=mclInit(byref(acast),0) didn't work. Press Enter to continue") 
    print '' 

try: 
    b=mclInit(acast,0) 
except Exception as ex: 
    print ex 
    raw_input("b=mclInit(acast,0) didn't work. Press Enter to continue") 
    print '' 

try: 
    b=mclInit(byref(acast1),0) 
except Exception as ex: 
    print ex 
    raw_input("mclInit(byref(acast1) didn't work. Press Enter to continue") 
    print '' 

try: 
    b=mclInit(acast1,0) 
except Exception as ex: 
    print ex 
    raw_input("b=mclInit(acast1,0) didn't work. Press Enter to continue") 
    print '' 

try: 
    b=mclInit(byref(acast2),0) 
except Exception as ex: 
    print ex 
    raw_input("mclInit(byref(acast2) didn't work. Press Enter to continue") 
    print '' 

try: 
    b=mclInit(acast2,0) 
except Exception as ex: 
    print ex 
    raw_input("b=mclInit(acast2,0) didn't work. Press Enter to continue") 
    print '' 

raw_input("Reached the end!!!! Press enter to close") 

Edit: Solo l'aggiunta nel eccezioni pitone getta

a= 
None 
acast= 
<__main__.LP_c_char_p object at 0x00000000034E68C8> 
acast1= 
<ctypes.LP_c_char object at 0x00000000034E6948> 

[Error -529697949] Windows Error 0xE06D7363 
Exception occurred. b=mclInit(None,0) didn't work. Press Enter to continue 

argument 1: <type 'exceptions.TypeError'>: expected LP_LP_c_char instance instea 
d of pointer to LP_c_char_p 
b=mclInit(byref(acast),0) didn't work. Press Enter to continue 

argument 1: <type 'exceptions.TypeError'>: expected LP_LP_c_char instance instea 
d of LP_c_char_p 
b=mclInit(acast,0) didn't work. Press Enter to continue 

[Error -529697949] Windows Error 0xE06D7363 
mclInit(byref(acast1) didn't work. Press Enter to continue 

[Error -529697949] Windows Error 0xE06D7363 
b=mclInit(acast1,0) didn't work. Press Enter to continue 

argument 1: <type 'exceptions.TypeError'>: expected LP_LP_c_char instance instea 
d of pointer to LP_LP_c_char 
mclInit(byref(acast2) didn't work. Press Enter to continue 

[Error -529697949] Windows Error 0xE06D7363 
b=mclInit(acast2,0) didn't work. Press Enter to continue 

EDIT 2

Così si scopre mi mancava una chiamata a mclmcrInitialize() come @eryksun aveva sottolineato . Ora posso chiamare le funzioni (evviva!) Ma l'inizializzazione non ha esito positivo :(. Quindi alcuni progressi, ma ancora lavoro da fare! Ecco il codice nel caso in cui è utile a chiunque.Ho un numero di chiamate a mclIsMCRInitialized() e mclGetLastErrorMessage() in . là che sono bulking le cose un po ', ma potrebbe fornire utili informazioni di debug

from ctypes import * 

libmcr=cdll.mclmcrrt8_1 

# Load mclmcr library 
mclmcr_dll = cdll.LoadLibrary('C:\\Program Files\\MATLAB\\MATLAB Compiler Runtime\\v81\\bin\\win64\\mclmcr.dll') 
# Load mclbase library 
mclbase_dll = cdll.LoadLibrary('C:\\Program Files\\MATLAB\\MATLAB Compiler Runtime\\v81\\bin\\win64\\mclbase.dll') 

# Call mclmcrInitialize() 
mclmcrInit = mclmcr_dll.mclmcrInitialize 
mclmcrInit.argtypes = None 
mclmcrInit.restypes = c_bool 
a = mclmcrInit() 
print "mclmcrInitialize returned " 
print a 

# call mclIsMCRInitialized() 
mclIsMCRInit = mclbase_dll.mclIsMCRInitialized 
mclIsMCRInit.argtypes = None 
mclIsMCRInit.restype = c_bool 
b = mclIsMCRInit() 
print "mclIsMCRInitialized = " 
print b 

# Call mclGetLastErrorMessage() 
mclGetLastErrMsg = mclbase_dll.mclGetLastErrorMessage 
mclGetLastErrMsg.argtypes = None 
mclGetLastErrMsg.restypes = c_char_p 
err = mclGetLastErrMsg() 
print "mcl last error returns " 
print err 

# call mclInitializeApplication(NULL,0) 
mclInit = mclbase_dll.mclInitializeApplication 
mclInit.argtypes = [POINTER(c_char_p),c_size_t] 
mclInit.restype = c_bool 
b = mclInit(None,0) 
print "mclInitializeApplication returned " 
print b 


# call mclIsMCRInitialized() 
mclIsMCRInit = mclbase_dll.mclIsMCRInitialized 
mclIsMCRInit.argtypes = None 
mclIsMCRInit.restype = c_bool 
b = mclIsMCRInit() 
print "mclIsMCRInitialized = " 
print b 

# Call mclGetLastErrorMessage() 
mclGetLastErrMsg = mclbase_dll.mclGetLastErrorMessage 
mclGetLastErrMsg.argtypes = None 
mclGetLastErrMsg.restypes = c_char_p 
err = mclGetLastErrMsg() 
print "mcl last error returns " 
print err 

# Call mclTerminateApplication() 
mclTerminate = mclbase_dll.mclTerminateApplication 
mclTerminate.argtypes = None 
mclTerminate.restype = c_bool 
f = mclTerminate() 
print "mclTerminateApp returned " 
print f 

Ecco l'output in pitone:

mclmcrInitialize returned 
-2147483647 
mclIsMCRInitialized = 
False 
mcl last error returns 
124384774 
mclInitializeApplication returned 
False 
mclIsMCRInitialized = 
False 
mcl last error returns 
128050512 
mclTerminateApp returned 
True 
+1

È solo 'mclInit (None, 0)'. Il fatto che tu stia vedendo un'eccezione VC++ non gestita ('0xE06D7363', cioè" msc ") implica un problema più profondo. C'è qualcosa che deve essere eseguito prima di inizializzare MATLAB? Vedo riferimenti a 'mclmcrInitialize'. – eryksun

+2

Per inciso, i ctypes non supportano le eccezioni C++ in generale. Stai vedendo solo l'eccezione VC++ perché Microsoft lo implementa usando un'eccezione di Windows gestita da ctypes. Normalmente un'eccezione C++ non gestita interromperebbe il processo. – eryksun

+0

Penso che la mia esclusione di 'mclmcrInitialize' possa essere parte del problema.Ho seguito il modulo generale fornito qui [collegamento] (http://blogs.mathworks.com/loren/2011/02/03/creating-c-shared-libraries-and-dlls/) che non sembra menzionarlo ma ora so di cercarlo, sto vedendo molto riferimento ad esso. Ti riporterò se avrò tutto pronto e funzionante! – ClaireM

risposta

0

Mentre stiamo indovinando, si potrebbe provare:

mclInit.argtypes = [POINTER(c_char_p), c_size_t] 
a = POINTER(c_char_p)() 
b = c_size_t(0) 
ret = mclInit(byref(a), b) 
+0

Vale la pena provare, ma sfortunatamente il nostro vecchio amico '[Errore -529697949] Errore Windows 0xE06D7363' è il risultato quando lo eseguo. Penso che l'impostazione del tipo degli argomenti sia corretta, ma ora sospetto che ci sia qualcos'altro che non è quello che causa problemi. – ClaireM

1

Sto postando questo in risposta a una richiesta di @Krcevina. Purtroppo ho dovuto disinstallare MCR a causa di limiti di spazio sul mio PC, quindi non sono stato in grado di testare questo oggi, ma penso che questo codice dovrebbe essere ragionevolmente funzionale e stabile. Ho provato a postarlo nei commenti ma non sembra consentire frammenti di codice di grandi dimensioni, quindi ho creato questa risposta. Inizializza e termina semplicemente l'MCR e la mia DLL. Ovviamente dovrai cambiare i nomi dei percorsi ecc. Per adattarli al tuo caso. Non ero arrivato a chiamare una funzione dalla DLL o passare variabili a dette funzioni, ma spero che questo sia di qualche utilità per voi.

Questo è quanto ho ottenuto con questo problema. Il nuovo motore Python su Matlab R2014b significava che non avevo bisogno di continuare così.

from ctypes import * 

libmcr=cdll.mclmcrrt8_1 

# Just check to make sure its 64bit python I'm using... 
print "4 for 32bit, 8 for 64bit:" 
print sizeof(c_voidp) 

# Load mclmcr library 
mclmcr_dll = cdll.LoadLibrary('C:\\Program Files\\MATLAB\\MATLAB Compiler Runtime\\v81\\bin\\win64\\mclmcr.dll') 
# Load mclbase library 
mclbase_dll = cdll.LoadLibrary('C:\\Program Files\\MATLAB\\MATLAB Compiler Runtime\\v81\\bin\\win64\\mclbase.dll') 
# Load matrix library 
matrix_dll = cdll.LoadLibrary('C:\\Program Files\\MATLAB\\MATLAB Compiler Runtime\\v81\\bin\\win64\\libmx.dll') 

# Load ClairesTestInterface library 
claires_dll = cdll.LoadLibrary('ClairesTestCompile.dll') 

#typedef int (*mclMainFcnType)(int, const char **); 
mclMainFcnType=CFUNCTYPE(c_int, c_int, POINTER(c_char_p)) # (returnvalu, arg1, arg2) 


def run_main(argc,argv): 
    print "run_main entered." 
    # call mclInitializeApplication(NULL,0) 
    mclInitializeApplication = mclbase_dll.mclInitializeApplication 
    mclInitializeApplication.argtypes = [POINTER(c_char_p),c_size_t] 
    mclInitializeApplication.restype = c_bool 
    b = mclInitializeApplication(None,0) 
    print "mclInitializeApplication returned " 
    print b 

    # call mclIsMCRInitialized() 
    mclIsMCRInitialized = mclbase_dll.mclIsMCRInitialized 
    mclIsMCRInitialized.argtypes = None 
    mclIsMCRInitialized.restype = c_bool 
    b = mclIsMCRInitialized() 
    print "mclIsMCRInitialized = " 
    print b 


    # call ClairesTestCompileInitialize() 
    ClairesTestCompileInitialize = claires_dll.ClairesTestCompileInitialize 
    ClairesTestCompileInitialize.argtypes = None 
    ClairesTestCompileInitialize.restype = c_bool 
    b = ClairesTestCompileInitialize() 
    print "ClairesTestCompileInitialize = " 
    print b 

    ## ------------------------------------------------------------------------------------------------------- 
    ## ------------------------------------------------------------------------------------------------------- 

    # call ClairesTestCompileTerminate() 
    ClairesTestCompileTerminate = claires_dll.ClairesTestCompileTerminate 
    ClairesTestCompileTerminate.argtypes = None 
    ClairesTestCompileTerminate.restype = None 
    ClairesTestCompileTerminate() 
    print "ClairesTestCompileTerminate has run " 

    # Call mclTerminateApplication() 
    mclTerminateApplication = mclbase_dll.mclTerminateApplication 
    mclTerminateApplication.argtypes = None 
    mclTerminateApplication.restype = c_bool 
    f = mclTerminateApplication() 
    print "mclTerminateApp returned " 
    print f 

    print "Reached the end of run_main()!!!" 
    return b 

def main(): 

    print "main() entered." 
    # Call mclmcrInitialize() 
    mclmcrInitialize = mclmcr_dll.mclmcrInitialize 
    mclmcrInitialize.argtypes = None 
    mclmcrInitialize.restypes = c_bool 
    a = mclmcrInitialize() 
    print "mclmcrInitialize returned " 
    print a 

    #LIBMWMCLBASE_API_EXTERN_C int mclRunMain(mclMainFcnType run_main, int argc, const char **argv); 

    mclRunMain=mclbase_dll.mclRunMain 
    mclRunMain.argtypes = [mclMainFcnType, c_int, POINTER(c_char_p)] 
    mclRunMain.restype = c_int 

    try: 
     _run_main = mclMainFcnType(run_main) # reference the callback to keep it alive 
    except Exception as ex: 
     print ex 
    #print "callback referenced to keep it alive." 

    c = mclRunMain(_run_main, 0, None) 
    print "mclRunMain returned " 
    print c 
    raw_input("Reached the end of main()! Press enter to close") 


main() 
Problemi correlati