2014-05-13 10 views
5

का उपयोग कर फोरट्रान डीएलएल को स्ट्रिंग पास करना मैं पाइथन 2.7 में डीटीएल लोड करने की कोशिश कर रहा हूं। डीएलएल फोरट्रान का उपयोग करके लिखा गया था और इसमें कई सबराउटिन हैं। मैं सफलतापूर्वक निर्यात किए गए कार्यों में से कुछ को स्थापित करने में सक्षम था कि long और double पॉइंटर्स तर्क के रूप में।सीटीपीएस और पायथन

import ctypes as C 
import numpy as np 

dll = C.windll.LoadLibrary('C:\\Temp\\program.dll') 
_cp_from_t = getattr(dll, "CP_FROM_T") 
_cp_from_t.restype = C.c_double 
_cp_from_t.argtypes = [C.POINTER(C.c_longdouble), 
        np.ctypeslib.ndpointer(C.c_longdouble)] 

# Mixture Rgas function 
_mix_r = getattr(dll, "MIX_R") 
_mix_r.restype = C.c_double 
_mix_r.argtypes = [np.ctypeslib.ndpointer(dtype=C.c_longdouble)] 

def cp_from_t(composition, temp): 
    """ Calculates Cp in BTU/lb/R given a fuel composition and temperature. 

    :param composition: numpy array containing fuel composition 
    :param temp: temperature of fuel 
    :return: Cp 
    :rtype : float 
    """ 
    return _cp_from_t(C.byref(C.c_double(temp)), composition) 

def mix_r(composition): 
    """Return the gas constant for a given composition. 
    :rtype : float 
    :param composition: numpy array containing fuel composition 
    """ 
    return _mix_r(composition) 

# At this point, I can just pass a numpy array as the composition and I can get the 
# calculated values without a problem 
comps = np.array([0, 0, 12.0, 23.0, 33.0, 10, 5.0]) 
temp = 900.0 

cp = cp_from_t(comps, temp) 
rgas = mix_r(comps) 

अभी तक, बहुत अच्छा है।

समस्या पैदा होती है जब मैं एक और सबरूटीन जो इनपुट के रूप में कुछ तार की जरूरत है Function2 कहा जाता है की कोशिश करो। तार सभी निश्चित लंबाई (255) हैं और वे प्रत्येक स्ट्रिंग पैरामीटर की लंबाई के लिए भी पूछते हैं।

समारोह फोरट्रान में कार्यान्वित किया जाता है इस प्रकार है:

Subroutine FUNCTION2(localBasePath,localTempPath,InputFileName,Model,DataArray,ErrCode) 
!DEC$ ATTRIBUTES STDCALL,REFERENCE, ALIAS:'FUNCTION2',DLLEXPORT :: FUNCTION2 
Implicit None 
Character *255 localBasePath,localTempPath,InputFileName 
Integer *4 Model(20), ErrCode(20) 
Real  *8 DataArray(900) 

अजगर में समारोह प्रोटोटाइप की स्थापना की है के रूप में

function2 = getattr(dll, 'FUNCTION2') 
function2.argtypes = [C.POINTER(C.c_char_p), C.c_long, 
         C.POINTER(C.c_char_p), C.c_long, 
         C.POINTER(C.c_char_p), C.c_long, 
         np.ctypeslib.ndpointer(C.c_long , flags='F_CONTIGUOUS'), 
         np.ctypeslib.ndpointer(C.c_double, flags='F_CONTIGUOUS'), 
         np.ctypeslib.ndpointer(C.c_long, flags='F_CONTIGUOUS')] 

इस प्रकार है और मैं का उपयोग कर इसे कहते:

base_path = "D:\\Users\\xxxxxxx\\Documents\\xxxxx\\".ljust(255) 
temp_path = "D:\\Users\\xxxxxxx\\Documents\\xxxxx\\temp".ljust(255) 
inp_file = "inp.txt".ljust(255) 

function2(C.byref(C.c_char_p(base_path)), 
        C.c_long(len(base_path)), 
        C.byref(C.c_char_p(temp_dir)), 
        C.c_long(len(temp_dir))), 
        C.byref(C.c_char_p(inp_file)), 
        C.c_long(len(inp_file)), 
        model_array, 
        data_array, 
        error_array) 

तार अनिवार्य रूप से पथ हैं। फ़ंक्शन Function2 पथ को पहचानता नहीं है और अंत में कुछ गैर-पठनीय पात्रों के साथ एक त्रुटि संदेश साबित करता है, जैसे:

forrtl: severe (43): file name specification error, unit 16, D:\Users\xxxxxxx\Documents\xxxxx\ωa

मैं जो समारोह प्राप्त करना चाहता था वह D:\Users\xxxxxxx\Documents\xxxxx\ था। जाहिर है, तार सही ढंग से पारित नहीं होते हैं।

मैंने पढ़ा है कि पायथन NULL समाप्त तारों का उपयोग करता है। फोर्ट्रान डीएलएल के तारों को पार करते समय क्या यह समस्या हो सकती है? यदि हां, तो मैं इसके आसपास कैसे हो सकता हूं?

कोई सिफारिशें?

+0

ठीक है। मूल्य से गुजरने के लिए 'argtypes' को बदल देगा। पिछली टिप्पणी के लिए, आप सही हैं। यह प्रोटोटाइप समारोह होना चाहिए था। ऊपर परिवर्तन किया है। कुछ कोड को सरल बनाना था क्योंकि इसे मूल रूप से कक्षा के रूप में लागू किया गया था। – d0m1n0

+0

@eryksun ने मदद की। अब तारों को correclty पारित किया जा रहा है। डीएलएल को अभी भी 'फंक्शन 2' के साथ परेशानी है। इसके लिए अपने लेखकों के साथ काम करना होगा। – d0m1n0

उत्तर

3

@eryksun से निम्नलिखित टिप्पणी, मैंने इसे काम करने के लिए निम्नलिखित परिवर्तन किए हैं।

बदल दिया argtypes रहे हैं:

function2 = getattr(dll, 'FUNCTION2') 
function2.argtypes = [C.c_char_p, C.c_long, 
        C.c_char_p, C.c_long, 
        C.c_char_p, C.c_long, 
        np.ctypeslib.ndpointer(C.c_long , flags='F_CONTIGUOUS'), 
        np.ctypeslib.ndpointer(C.c_double, flags='F_CONTIGUOUS'), 
        np.ctypeslib.ndpointer(C.c_long, flags='F_CONTIGUOUS')] 

और बजाय byref के रूप में स्ट्रिंग में उत्तीर्ण होने की, मैं इसे निम्नलिखित करने के लिए बदल दिया है।

base_path = "D:\\Users\\xxxxxxx\\Documents\\xxxxx\\".ljust(255) 
temp_path = "D:\\Users\\xxxxxxx\\Documents\\xxxxx\\temp".ljust(255) 
inp_file = "inp.txt".ljust(255) 

function2(base_path, len(base_path), temp_dir, len(temp_dir), inp_file, len(inp_file), 
      model_array, data_array, error_array) 

यह मूल्यों को सीधे पास करने के लिए पर्याप्त था।

+1

[मिश्रित भाषा प्रोग्रामिंग] के लिए इंटेल के दस्तावेज़ों के अनुसार (https://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/2011Update/fortran/lin/bldaps_for/common/bldaps_bk_hndl_dtypes.htm) , लम्बाई तर्क सूची के अंत में जोड़ दी जाती है, इंटरलीव नहीं। इसके अलावा 32-बिट प्रक्रिया में तर्क 'c_int32' और 64-बिट प्रक्रिया में' c_int64' है।विंडोज़ में 'c_long' हमेशा एक' c_int32' है, लेकिन व्यवहार में आपको कोई समस्या नहीं होगी जब तक कि आपको एक स्ट्रिंग की आवश्यकता न हो जो '2 ** 31 - 1' से अधिक हो। – eryksun

संबंधित मुद्दे