как автоматически сгенерировать уникальный класс c на основе файла

#c #game-engine #game-development

Вопрос:

позвольте мне предварить этот вопрос, сказав, что я понятия не имею, задаю ли я правильный вопрос. Я довольно новичок в c и еще не разобрался во всех его нюансах, но я кодировал на других языках ООП почти 7 лет.

Изначально я спросил: есть ли способ взять текстовый файл и автоматически сгенерировать код c ? Если да, то как мне это сделать? Каковы некоторые ресурсы, которые объясняют процесс?

но чтобы уточнить, чего я действительно хочу: есть ли какой-нибудь способ взять текстовый файл или другой тип файла (например, json) и использовать его для создания скомпилированного класса c или другого скомпилированного объекта, который может быть сопряжен с c ?

Конечный результат не обязательно должен быть читаемым человеком, и он может зависеть от системы. Я хочу иметь возможность делать это во время компиляции. Это не обязательно должно происходить во время выполнения. Я буду знать во время выполнения, какие классы мне нужны. Просто классы, которые я буду создавать (а их будет много), все очень похожи и просто отличаются в нескольких ключевых местах. Итак, мне нужен способ сообщить компьютеру важные вещи (которые могут занимать всего 5 или 6 строк кода) и заставить его сгенерировать остальные 30 строк кода boiler plate.

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

Кто-то прокомментировал, что я должен упростить пример. Итак, поехали.

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

Например, имея файл с именем example.txt который выглядит примерно так.

 objectGenerator ExampleClass {
autofunction[hello world]
}
 

Затем я надеюсь создать что-то, что функционирует аналогично классу c , например

 class ExampleClass
{
public:
    void callAutoFunctions()
    {
        helloWorld();
    }

private:
    AutoFunction helloWorld;
};
 

затем в моем main.cpp например, я мог бы позвонить

 void main()
{
    GeneratedClasses::ExampleClass exampleClass; 
    exampleClass.callAutoFunctions();
}
 

для печати «hello world».

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

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

p.s. Я пытаюсь переделать игру, которую я создал в python arcade более года назад, но на c , чтобы она работала лучше, и я действительно могу создать exe-файл для игры, который я могу подарить друзьям или добавить в itch.io . Я знаю, что с моей стороны очень смело предполагать, что я смогу создать жизнеспособную, продаваемую игру, когда я кодировал на c менее года, но я человек, ориентированный на выполнение задач, и у меня не было бы мотивации изучать c , который мне нужен, не делая что-то занововершина, подобная этой.

Комментарии:

1. В C есть шаблоны.

2. вы можете использовать скрипт для автоматизации генерации, компиляции и лайка кода. В чем ваш вопрос?

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

4. C — самый сложный язык программирования общего назначения, используемый сегодня. Требуется около 3-5 лет обучения, руководствуясь несколькими учебниками по C , прежде чем вы получите средние знания и понимание основ C : классы, методы, наследование, множественное наследование, полиморфизм, перегрузка, контейнеры, алгоритмы, многопоточность, шаблоны, пакеты параметров, признаки типов и многое другое. И только после того, как вы твердо усвоите основы, можно приступить к изучению специализированных областей, таких как написание «игрового движка». Без четкого понимания основ это всегда заканчивается плачевно.

5. C просто не работает таким образом. Все классы в программе на C объявляются и определяются во время компиляции. Классы — это не то, что может быть создано ad-hoc во время выполнения. «создает мне скомпилированный двоичный файл c » — это то, что делает компилятор C . Я полагаю, что можно было бы написать некоторый код, который записывает исходный файл C , а затем запускает компилятор C для компиляции его в исполняемый файл. Но я сомневаюсь, что этот карточный домик долго продержится.

Ответ №1:

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

 // Player.hpp

#include <memory>

struct IPlayer {
  virtual void run() = 0;
  virtual ~IPlayer() = defau<
};

std::unique_ptr<IPlayer> getPlayer();
 

Затем используйте его в своей программе, не предоставляя реализацию:

 // main.cpp

#include "Player.hpp"

int main() {
  auto player = getPlayer();
  player->run();
}
 

Затем вы компилируете его без привязки:

 $ clang   -c main.cpp -O3 -Wall -Wextra
 

Теперь вы работаете над своими реальными реализациями:

 // FastPlayer.cpp

#include "Player.hpp"

struct FastPlayer : IPlayer {
  void run() override { /* ... */ }
}

std::unique_ptr<IPlayer> getPlayer() {
  return std::unique_ptr<IPlayer>{ new FastPlayer };
}
 

Затем скомпилируйте любую реализацию, которую вы хотите протестировать сейчас, и свяжите ее с двоичным файлом, который вы скомпилировали ранее:

 $ clang   FastPlayer.cpp main.o -O3 -Wall -Wextra
 

Таким образом, вы можете легко менять реализации, чтобы протестировать множество функций. Это безопаснее, чем загрузка произвольного кода во время выполнения.

В идеале, вы не должны делать это вручную, и система сборки, такая как CMake, справится с этим за вас.

Ответ №2:

Вы не можете добавлять новые классы в свое приложение после его сборки (компиляции и ссылки в exe-файл).

Технически вы можете использовать C для написания своего собственного языка, именно так они создали Python или Java. Просто используйте их для начала, если это правильный инструмент. Потребуется 400 лет, чтобы написать что-то подобное самостоятельно.

Можно использовать внешние двоичные файлы. Вы должны ссылаться на них во время сборки. Библиотеки обычно используют интерфейс C, легко найти функцию по уникальному имени и вызвать ее. Чтобы использовать библиотеки c , ваше приложение и библиотека должны быть созданы одним и тем же компилятором c , с той же версией компилятора и настройками. Это полезно, например, для доступа к стандартным библиотекам.

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

Вы можете писать классы для game, player, ball и т. Д. Сохраните предыдущее состояние в файле и прочитайте его снова. cgame может иметь свой собственный cplayer и cball т. Д. Это подойдет для любой ситуации.

В C нет таких функций, как Javascript, которые могут распознаваться onclick() как команда. Вы должны сохранить строку "onclick" в файле, прочитать ее, проанализировать и интерпретировать самостоятельно.

Ближайшая задача — сохранить простую структуру данных:

 struct plain_data
{
    int speed;
    int size;
    int previous;
    //don't put classes and pointers here
};

plain_data data = { 1,2,3 };
std::ofstream fout("file.dat", std::ios::binary);
fout.write((char*)amp;data, sizeof(data));
fout.close();

std::ifstream fin("file.dat", std::ios::binary);
fin.read((char*)amp;data, sizeof(data));
fin.close();
 

Редактировать

Допустим, вы хотите создать игру на c , такую как Halo или Doom Eternal. Это можно сделать без языка сценариев. Вам просто нужны внешние библиотеки для обработки изображений и т. Д.

Теперь предположим, что вы хотите создать программу, которая может играть в любую игру. На момент разработки этой программы вы ничего не знаете об этой игре, это может быть пинг-понг, или это может быть карточная игра, или что-то еще. Для этого потребуется язык сценариев.

Последнее является более сложной задачей. Это не должно быть вашей первой попыткой в разработке на c . Вы могли бы рассмотреть Java-подобные языки с «компилятором точно в срок», которые принимают текстовые команды и превращают их в двоичные файлы во время выполнения.

Комментарии:

1. Написание собственного языка сценариев или DSL определенно не «занимает 400 лет», это то, что можно легко сделать менее чем за неделю (JavaScript был создан за 10 дней). Создание инструментов для такого языка — это другой вопрос (а также является ли пользовательский язык правильным решением)

2. @UnholySheep Это был оригинальный Javascript с несколькими функциями, в нем не было классов. Чтобы написать язык сценариев с эффективностью Java или Python и их функциональностью, я думаю, 400 лет. Это основано на мнениях, я действительно не знаю.

3. Спасибо! Я думаю, что я ищу внешние двоичные файлы, как вы сказали. Я хорошо знаю, что не мог этого сделать во время выполнения, но я не хочу. что я убираю из этого, так это то, что мне придется написать свой собственный (очень простой) DSL, который я интерпретирую во внешний двоичный файл, который я связываю со своей программой во время компиляции. Причина, по которой я даже хочу это сделать, заключается в том, что все в моей игре является общим. Технически, если бы я захотел, я мог бы поместить сценарий перемещения игрока в случайное дерево, просто изменив одну строку в другом файле и скомпилировав его.

4. Я отредактировал ответ, возможно, он станет более понятным.