Укажите порядковые номера экспортируемых функций C ++ в DLL - PullRequest
0 голосов
/ 18 декабря 2008

Я пишу DLL со смешанным кодом C / C ++. Я хочу указать порядковые номера экспортируемых функций. Поэтому я создал файл .DEF, который выглядит следующим образом

LIBRARY LEONMATH

EXPORTS

    sca_alloc   @1
    vec_alloc   @2
    mat_alloc   @3

    sca_free    @4
    vec_free    @5
    mat_free    @6

    ...

Я хотел бы также указать порядковые номера моих функций C ++ и методов класса. Я попытался с помощью средства проверки зависимостей добавить искаженные имена моих функций в файл .DEF:

    ??0CScalar@@QAE@XZ      @25
    ??0CScalar@@QAE@O@Z     @26
    ??0CScalar@@QAE@ABV0@@Z @27
    ??1CScalar@@QAE@XZ      @28

Но это не удалось. Есть идеи, почему это может происходить?


РЕДАКТИРОВАТЬ: Кауппи сделал хорошее наблюдение, поэтому я добавляю дополнительную информацию к вопросу.

  • Платформа: Windows (и меня не интересует переносимость)
  • Компилятор: Компилятор Microsoft C ++ (я использую VS2005)
  • Почему я хочу это сделать?: Использование ординалов имеет то преимущество, что позволяет мне вызывать экспортированные функции C ++ из кода C.

Ответы [ 2 ]

4 голосов
/ 18 декабря 2008

Ну, у меня нет опыта работы с ординалами (которые выглядят как некрасивые, специфичные для компилятора вещи), но я могу помочь вам сделать совместимый код C ++ / C.

Предположим, в C ++ ваш заголовочный файл выглядит так:

class MyClass
{
    void foo(int);
    int bar(int);
    double bar(double);
    void baz(MyClass);
};

Вы можете сделать его C-совместимым, выполнив следующие действия:

#ifdef __cplusplus
#define EXTERN_C extern "C"
// Class definition here; unchanged
#else
#define EXTERN_C
typedef struct MyClass MyClass;
#endif

EXTERN_C void MyClass_foo (MyClass*, int);
EXTERN_C int MyClass_bar_int (MyClass*, int);
EXTERN_C double MyClass_bar_double (MyClass*, double);
EXTERN_C void MyClass_baz (MyClass*, MyClass*);

В исходном файле C ++ вы просто определяете различные функции extern "C" для передачи нужным функциям-членам, например так (это только одна; остальные работают аналогично)

extern "C" void MyClass_foo (MyClass* obj, int i)
{
  obj->foo(i);
}

В этом случае код будет иметь интерфейс C без необходимости вообще изменять код C ++ (за исключением объявлений в заголовке; но они также могут быть перемещены в другой файл "myclass_c.h" или тому подобное). Все функции, объявленные / определенные extern "C", не будут повреждены, поэтому вы можете легко выполнять другие операции с ними. Вы также, вероятно, захотите, чтобы функции создавали / уничтожали экземпляры MyClass (вы, конечно, можете использовать new / delete для этого).

2 голосов
/ 18 декабря 2008

Вы сказали: «Использование ординалов дает мне возможность вызывать экспортированные функции C ++ из кода C». Извините, что это неверно.

Функции-члены класса C ++ имеют специальное соглашение о вызовах, которое требует невидимого этого значения, передаваемого в регистр / параметр, зависящий от реализации. А также вам нужно передать экземпляр класса, чего вы не можете выполнить в C.

Мне известны только два варианта использования: более быстрое динамическое связывание DLL и меньшая таблица импорта. Просто проверьте файл mfc70.dll в каталоге system32 с помощью средства отслеживания зависимостей.

...