2016-08-11 8 views
1

У меня есть библиотека C, которая имеет что-то вроде ниже:D интеграции с C библиотеки причин тарабарщина для вывода

Abc.h файл

typedef struct 
{ 
    uint8_t dbtype; 
    uint32_t dbcount; 
} Abc; 

void test_string(Abc* abcobj, char* strA, char* strB); 
Abc* create_abc(void); 

Abc.c

void test_string(Abc* abcobj, char* strA, char* strB) 
{ 
    printf("Str A is %s and str B is %s\n", strA, strB); 
    return; 
} 

Abc* create_abc() 
{ 
    Abc* abcobj; 
    abcobj = (Abc*) calloc(1, sizeof(Abc)); 
    return abcobj; 
} 

сейчас , Я пытаюсь назвать эти функции в своем D-коде.

testD.d

module testD; 

import std.stdio; 
import core.stdc.string; 
import core.sys.posix.dlfcn; 

extern (C) 
{ 
    struct Abc { 
     ubyte dbtype; 
     int dbcount; 
    } 
} 

int main() { 
    auto lib = dlopen("Abc.so".ptr, RTLD_LAZY | RTLD_LOCAL); 

    if (lib is null) { 
     return -1; 
    } 

    void function(Abc* abcobj, char* strA, char* strB) test_string = cast(void function(Abc* abcobj, char* strA, char* strB))dlsym(lib, "test_string"); 
    Abc* function() create_abc = cast(Abc* function())dlsym(lib, "create_abc"); 

    char* strA = cast(char*)("this is string one"); 
    char* strB = cast(char*)("this is string two"); 

    Abc* abcobj = create_abc(); 
    test_string(abcobj, strA, strB); 

    if (dlclose(lib) == 0) { 
     return 0; 
    } 
    else { 
     return -1; 
    } 
} // main() function 

Я компилировать testD.d с помощью:

DMD testD.d

Затем запустить ./testD

Когда test_string выводит предложение , значение для strA всегда выдается как тарабарщина, в то время как strB получается просто отлично.

Почему это происходит ???

+0

Некоторые другие вещи: 'dbcount' должен быть' uint' в D для соответствия 'uint32_t' в C, а' test_string' должен принимать 'const char *', поскольку строки не нужно изменять (и лить D строковые литералы типа 'immutable (char) []' to 'char *' - технически неопределенное поведение). –

+0

Сменили тип на uint и теперь используя const char *. Часть каста изменилась на char * strA = "это строка одна" .dup.ptr; – Vlam

ответ

5

Поскольку .so было сделано с C, вы собрали библиотеку с C связи, однако при импорте символов, вы отбрасывая тот факт, что означает, что D пытается использовать D соглашение о вызовах в вызывают код, который отличается от соглашения о вызове C.

При импорте функции, необходимо указать на это, так dlsym линии должны выглядеть следующим образом:

extern (C) void function(Abc* abcobj, char* strA, char* strB) test_string = 
    cast(void function(Abc* abcobj, char* strA, char* strB))dlsym(lib, "test_string"); 
extern (C) Abc* function() create_abc = 
    cast(Abc* function())dlsym(lib, "create_abc"); 

После того, как вы получите соглашение о вызове права, правильные результаты должны выйти из вызова.

 Смежные вопросы

  • Нет связанных вопросов^_^