Помимо заявленных аргументов и указателя this, какие еще аргументы получает конструктор c ++ (g ++), в каком порядке? - PullRequest
0 голосов
/ 06 ноября 2018

Я хочу вызвать конструктор C ++ из другого языка, и мне нужно знать, какие аргументы ему нужно предоставить. Я думаю, что это должны быть заявленные аргументы и указатель "это". Но указатель «this» идет первым или последним в Gnu G ++? И есть ли другие скрытые аргументы, кроме указателя "this"?

Другие вопросы, такие как искаженные имена, не включены в этот вопрос, поскольку у меня уже есть эти проблемы решены. Этот вопрос касается только аргументов конструктора. И конкретный язык, который я использую, также не является проблемой, поскольку он находится в стадии разработки, и этот вопрос относится в целом к ​​языкам, не относящимся к С ++, а не только к конкретному языку.

Отредактировано, чтобы добавить: Это для процессора Intel, использующего соглашения G ++. Это должно ответить на вопрос о том, что ABI участвует.

Что касается "extern C", то это не код C ++. Он вызывает код C ++, но поскольку это не сам код C ++, было бы бессмысленно использовать «extern C». Кроме того, вызываемый им код C ++ должен использоваться как есть, без добавления к нему таких вещей, как «extern C».

То, что я ищу, не является точным формальным определением соглашений о вызовах. Я просто хочу кое-что поэкспериментировать с. Например, как часто компиляторы C ++ помещают указатель «this» в позиции, отличные от первого аргумента? И как часто встречаются другие скрытые аргументы, кроме указателя «this». И если указатель «this» не первый, то он почти всегда последний или иногда посередине? И т.д.

Ответы [ 3 ]

0 голосов
/ 06 ноября 2018

Стандарт C ++ не определяет, как указатель this и любые аргументы передаются в конструктор (или любую функцию в этом отношении). Это работа ABI (Application Binary Interface), и различные компиляторы могут - и в реальном мире - использовать разные ABI. ABI не является частью стандарта C ++.

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

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

Практически, стандарт C ++ определяет, как он взаимодействует с C на уровне языка. C не может использовать все конструкции C ++, но функции extern "C" создаются компилятором C ++ таким образом, чтобы их можно было вызывать из C. Совместимые компиляторы C и C ++ - или код, который они генерируют - могут поэтому взаимодействовать, предполагая, что оба Компиляторы поддерживают один и тот же ABI. Например, g ++ (интерфейс компилятора gnu C ++) и gcc (интерфейс компилятора gnu C) предназначены для взаимодействия, но они (не обязательно) взаимодействуют с компиляторами других поставщиков. Технически может быть возможным, чтобы вывод машинного кода компилятором gnu C взаимодействовал с выводом кода компилятором C от другого поставщика, но для этого требуется очень подробное знание того, как работают ABI, поддерживаемые обоими компиляторами (и преднамеренная поддержка обоими поставщики).

Для того, чтобы другие языки могли взаимодействовать с C ++, эти опции менее просты. Обычно общим знаменателем является C - другие языки предоставляют возможность взаимодействия с C, как и C ++, поэтому некоторый интерфейс C используется в качестве посредника между ними. Например, код, который создает экземпляр объекта в C ++, может быть помещен в функцию extern "C". Затем этот код может быть скомпилирован с использованием компилятора C ++, и результирующая функция имеет интерфейс, позволяющий вызывать его из кода C. Если другой язык (или компилятор) поддерживает взаимодействие с C (то есть соответствует требованиям к правильному интерфейсу для вызова функции C), тогда эту функцию C можно вызывать из других языков.

0 голосов
/ 06 ноября 2018

Что касается "внешнего C", то это не код C ++.

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

Придерживайтесь C-совместимых интерфейсов. Вы не первый человек в мире, которому нужно создать объект C ++ из кода не-C ++. Каждый делает это с помощью extern "C" кода.

код C ++, который он вызывает, должен использоваться как есть, без добавления к нему таких вещей, как "extern C".

Вы ничего не добавляете к существующему коду для взаимодействия с ним. Вы пишете новый код C ++, заставляете его вызывать старый код C ++ и помечаете новый код extern C. Старый код никак не затрагивается.

0 голосов
/ 06 ноября 2018

Размещение указателя this в списке аргументов определяется реализацией. Если вы хотите взаимодействовать с другим языком, добавьте оболочку C:

// Your class
struct MyClass {
    MyClass(int, int);
    void doSomething(char,int);
};
// C wrapper
void* construct_MyClass(int a, int b) {
    return new MyClass(a, b);
}
void doSomething(void* thisPtr, char c, int a) {
    static_cast<MyClass*>(thisPtr)->doSomething(c, a);
}

Таким образом, компилятор позаботится о размещении параметров в ожидаемом порядке, оставляя ваш код вызывающей стороны для взаимодействия с C API. Вам нужно будет использовать extern C в объявлениях ваших функций C, чтобы сохранить имя для связи C.

...