Одно правило определения для библиотек DLL с точки зрения стандартов C ++ - PullRequest
0 голосов
/ 24 марта 2020

У меня плохо спроектированный заголовок библиотеки DLL, который использует TCHAR в своем заголовке в качестве члена структуры *:

struct A {
  int nType;
  TCHAR szData[128];
};

А также есть функция DLL, которая передала struct A** в качестве аргумента для возврата динамический c выделенный массив типа struct A и его длина:

void func(int *pnCount, struct A **ppArray);

Поскольку в библиотеке DLL мы используем многобайтовый набор символов в настройках проекта, TCHAR равен char , Но в приложении мы устанавливаем набор символов Unicode, и TCHAR на самом деле wchar_t.

Поскольку по какой-то причине я не могу изменить файл заголовка, как я могу вызвать эту функцию DLL, не нарушая правила?

  1. Применяется ли строгое правило алиасинга через границы библиотеки? Я думаю, что компилятор не может делать причудливые оптимизации на этом интерфейсе DLL.

  2. Если я сам определю структуру (без включения заголовка) в проекте приложения как:

struct A {
  int nType;
  char szData[128];
};

void func(int *pnCount, struct A **ppArray);

Похоже, я не нарушил ни одного правила, включая правило строгого алиасинга, не так ли?

Поскольку я должен включить заголовок, могу ли я использовать другое имя структуры, не нарушая строгое правило алиасинга или другие правила?
struct A2 {
  int nType;
  char szData[128];
};

3a. Похоже, мне нужно использовать какие-то приведения для архивирования, какие из них мне следует использовать?

3b. Или я могу переслать объявление функции DLL или динамически загрузить функцию DLL с другой подписью?

void func(int *pnCount, struct A2 **ppData);
А как насчет того, чтобы использование не выходило за границы библиотеки, а распространялось только на исходные файлы (единицы перевода)?

* Ниже приведен лишь упрощенный пример моего реального случая.


Обновление:

После прочтения ответа walnut я понял, что это может быть связано с правилом одного определения стандарта, а не со строгим правилом псевдонимов, поэтому я изменил название.

Кроме того, чтобы сделать его более конкретным c, я удалил тег C.

1 Ответ

1 голос
/ 24 марта 2020

Для C ++ с точки зрения стандартов (с учетом тега language-lawyer). На практике вы можете получить гораздо больше:

  1. Применяется ли строгое правило алиасинга через границы библиотеки? Я думаю, что компилятор не может делать причудливые оптимизации на этом интерфейсе DLL.

Да, это так. Однако, насколько я могу судить, вы на самом деле ничего не спрашиваете о строгом правиле псевдонимов. Ваши вопросы скорее касаются правила одного определения.

Если я определю структуру самостоятельно (без включения заголовка) в проекте приложения как:

Да, это вполне нормально, если последовательность токенов (после замена макроса) точно так же, как в заголовке, использованном для создания библиотеки.

Поскольку я должен включить заголовок, могу ли я использовать другое имя структуры, не нарушая строгое правило алиасинга или другие правила?

Нет, вы не можете. Вы бы объявили другой тип и другую функцию, и доступ к A2 через указатель на A (или наоборот) был бы неопределенным поведением.

Кроме того, включение исходного заголовка (без защита его каким-либо образом, чтобы не включать определение несоответствия), уже привела бы к нарушению программой правила одного определения и, следовательно, к неопределенному поведению.

А как насчет того, если использование не за пределами библиотеки, а только между исходными файлами (единицами перевода)?

Те же ответы. Стандарт не знает разницы между ними. Это относится только к единицам перевода.

...