2016-01-16 64 views
3

要將Fortran字符串傳遞給C,隱藏參數也會與變量的大小一起傳遞。這裏有一個工作FORTRAN定義,以及C(實際上是C++/CLI)方法:多個Fortran字符串應該如何傳遞給C?

interface 
    subroutine AppendExtension(
+  Filename) 
+  bind(C, name="AppendExtension") 
    character *1, intent(inout):: Filename 
    end subroutine AppendExtension 
    end interface 

和這裏的C++/CLI,它被稱爲:

extern "C" { 
    void __declspec(dllexport) __cdecl AppendExtension(
             char * name, 
             int buffersize) 
{ 
    String^ clistr = gcnew String(name); 
    clistr = System::IO::Path::ChangeExtension(clistr->Trim(), gcnew String("OUT")); 
    IntPtr p = Marshal::StringToHGlobalAnsi(clistr); 
    char *pNewCharStr = static_cast<char*>(p.ToPointer()); 
    int cstrlen = strlen(pNewCharStr); 
    memcpy_s(name, buffersize, pNewCharStr, cstrlen); 
    if (cstrlen < buffersize) 
    { 
    // backfill with spaces, since a Fortran string is spaces on the right. 
    memset(&name[cstrlen], ' ', buffersize-cstrlen); 
    } 
    Marshal::FreeHGlobal(p); 
} 

以上正常工作(英特爾視覺Fortran語言2013 SP1)。

我現在想將兩個字符串傳遞給一個函數。下面是我所做的:

interface 
    subroutine ParseSpec(
+  Filename, Corename) 
+  bind(C, name="ParseSpec") 
    character *1, intent(inout):: Filename 
    character *1, intent(inout):: Corename 
    end subroutine ParseSpec 
    end interface 

下面是行動電話:

 CHARACTER*80 FILE_SPEC 
     CHARACTER*200 CORE_NAME 
     CALL ParseSpec(FILE_SPEC, CORE_NAME) 

和這裏的C++/CLI:

void __declspec(dllexport) __cdecl ParseSpec(char * name, char * corename, int namelen, int corelen) 
{ 
    // namelen and corelen both contain the length of "name". 
    ... 

有兩個隱藏的變量。我認爲他們應該爲我的兩個字符串中的每一個的緩衝區大小,一個用於「文件名」,另一個用於「核心名稱」。但都包含第一個緩衝區的緩衝區大小,即80.

我在哪裏出錯了?

回答

4

BIND(C)過程的調用約定可能與Fortran編譯器用於Fortran到Fortran調用的默認調用約定大不相同。您不應該依賴任何隱藏的CHARACTER長度參數(在一般情況下,您也不應該期望隱藏的參數類型爲int)。考慮到Fortran CHARACTER變量由該編譯器在內存中進行佈局的方式,我懷疑你是幸運的。

編譯器不需要爲BIND(C)過程傳遞長度,因爲與C可互操作的CHARACTER變量的唯一長度是1。但是,如果僞參數是一個數組(如果傳遞字符串而不是單個字符,則這是您想要的),那麼該數組的大小可能是非負數 - 對於KIND = C_CHAR的Fortran序列關聯規則字符意味着您可以將標量與數組關聯。

所有 - 更改Fortran函數聲明,以便字符參數是數組並添加參數以顯式傳遞這些數組的長度。

使用自由形式源,並假設默認字符相同C_CHAR類型:

interface 
    subroutine ParseSpec( & 
     Name, Name_len, & 
     Corename, Corename_len) & 
     bind(C, name="ParseSpec") 
    use, intrinsic :: iso_c_binding, only: c_int, c_char 
    integer(c_int), value :: Name_len 
    character(kind=c_char), intent(inout) :: Name(Name_len) 
    integer(c_int), value :: Corename_len 
    character(kind=c_char), intent(inout):: Corename(Corename_len) 
    end subroutine ParseSpec 
end interface 

USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_INT 
CHARACTER*80 FILE_SPEC 
CHARACTER*200 CORE_NAME 
CALL ParseSpec( & 
    FILE_SPEC, LEN(FILE_SPEC, KIND=C_INT), & 
    CORE_NAME, LEN(CORE_NAME, KIND=C_INT)) 
extern "C" void ParseSpec( 
    char* name, int name_len, 
    char* corename, int corelen); 
// Operations on name[0] to name[name_len-1] and 
// corename[0] through corename[core_len-1]... 
相關問題