Воскресенье, 19.05.2024, 04:30
Personal dimanche13 site
Главная | Регистрация | Вход Приветствую Вас Гость | RSS
Категории каталога
Мои статьи [22]
BlitzMax [17]
раздел содержит статьи относящиеся к языку программирования BlitzMax
SDL [9]
раздел содержит статьи на тему SDL
Code::Blocks [3]
в этом разделе рассказывается как прикрутить движок к интегрированной среде разработки(IDE) Code::Blocks
Форма входа
Поиск
Друзья сайта
Главная » Статьи » BlitzMax

BlitzMax и С. часть 2.

ВВЕДЕНИЕ.

Из прошлой части мы узнали как сделать функцию в С и как объявить и использовать ее в БМаксе. На этот раз попытаемся усложнить задачу. Мы возьмем язык С++, основной его фишкой является его ООП-составляющая. Попробуем сделать класс в С++, а объявлять объекты такого же типа и использовать его методы из Бмакса. Я видел 2 решения этой задачи. Начнем как и полагается с первой. Это решение первое лишь по моей классификации, потому что этот способ я попробовал первым, а второй естественно вторым ;)

ПЕРВЫЙ СПОСОБ.

Давайте опишем простенький прототип класса в С++.

// c_test_001.h

#ifndef _C_TEST_001_H_
#define _C_TEST_001_H_

#include <brl.mod/blitz.mod/blitz.h>

class myClass
{
 public:
  BBString* HelloWorld();
  BBString* Hello( BBString* name );
};

#endif

это h-файл (header), в нем показана структура класса. (Чтоб отпали все вопросы, то BBString* -это тоже самое, что и BВSTRING.) В классе всего два метода, один без параметров и второй с параметром БМакс-строки. Так же оба эти метода возвращают БМаксовскую строчку. Теперь немного теории. Первый способ подразумевает использование С-функций отвечающих за выполнение методов объекта. То есть к каждому методу объекта делается функция принимающая в параметре, сам экземпляр объекта и параметры вызываемого метода. Проще будет показать на примере: 

//просто возвращает приветствие миру от всего мира ко всему миру

BBString* myClass::HelloWorld()
{
 return bbStringFromCString("Hello World!");
}

//объединяется слово "привет" с именем того, кому он адресован
BBString* myClass::Hello( BBString* name )
{
 char buffer[30];
 sprintf(buffer, "Hello, %s !" , bbStringToCString( name ) );
 return bbStringFromCString( buffer );
}

это код 2 методов нашего простенького класса. Теперь нам необходимо создать функцию создания объекта данного типа:

myClass *create_obj_of_myClass()  // создадим и вернем объект типа myClass
{
  return new myClass;
}

и две функции отрабатывающие методы конкретного объекта передаваемого в параметре:

// передается объект и вызывается его метод HelloWorld()

BBString* myClass_HelloWorld( myClass* instance ) 
{
 return instance->HelloWorld();
}

// передается объект и строка и вызывается его метод HelloWorld()
BBString* myClass_Hello( myClass* instance, BBString *name ) {
 instance->Hello( name );

Как видите функции я назвал соответствующе, чтоб не запутаться. Теперь мы должны экспортировать эти функции в БМакс. Точнее это надо делать в начале файла *.cpp , вот так выглядит начало:

#include "c_test_001.h"
#include <stdio.h>

extern "C"{
 myClass *create_obj_of_myClass();
 BBString* myClass_HelloWorld( myClass* instance );
 BBString* myClass_Hello( myClass* instance, BBString *name );
}

Вот, так примерно оно и делается. Теперь надо написать БМакс-код. Конечно сначала берем функции экспортируемые С-файлом, затем создается тип похожий на наш С-класс:

SuperStrict

Import "c_test_001.cpp"  ' цепляем СPP-файл

Extern "C" ' экспортируем функции
 
 Function create_obj_of_myClass:Byte Ptr()
 Function myClass_HelloWorld:String( instance:Byte Ptr )
 Function myClass_Hello:String( instance:Byte Ptr, name:String )
 
End Extern

' создаем подобный класс
Type myType 
 
 Field instance:Byte Ptr   ' это будет указатель на класс
 
 Method New()
  instance = create_obj_of_myClass() ' вызываем функцию создания экземпляра класса
 End Method
 
 Method HelloWorld:String()
  Return myClass_HelloWorld( instance ) ' вызываем метод класса, передав указатель на себя
 End Method
 
 Method Hello:String( name:String )
  Return myClass_Hello( instance, name ) ' вызываем метод класса,передав указатель на себя и параметр метода
 End Method
  
End Type

'создаем

Local obj:myType = New myType

'исполняем

Print obj.HelloWorld()

Print obj.Hello("dimanche")

end

Вот так, я думаю все прошло без особых затруднений. :)

ВТОРОЙ СПОСОБ.

Второй способ проще чем первый, здесь не надо создавать функций обработки для методов объектов, что само по себе является дублированием кода. Здесь используется непосредственный вызов объектом его методов. Для этого в заголовочном файле все функции класса надо объявить виртуальными:

//c_test_002.h

#ifndef _C_TEST_002_H_
#define _C_TEST_002_H_

#include <brl.mod/blitz.mod/blitz.h>

class myClass
{
 public:
  virtual ~myClass() {}
  virtual BBString* HelloWorld();
  virtual BBString* Hello( BBString* name );
};

#endif

Тогда в файле *.cpp надо объвить только код этих методов и функцию создания экземпляра класса:

// c_test_002.cpp

#include "c_test_002.h"
#include <stdio.h>

extern "C"{
 myClass* create_obj_of_myClass();
}
 
myClass* create_obj_of_myClass()
{
  return new myClass;
}

BBString* myClass::HelloWorld()
{
 return bbStringFromCString("Hello World!");
}

BBString* myClass::Hello( BBString* name )
{
 char buffer[30];
 sprintf( buffer, "Hello, %s !" , bbStringToCString( name ) );
 return bbStringFromCString( buffer );
}

Заметьте что экспортируем теперь только функцию создания объекта, и нам больше не нужны другие функции обвязки, как в первом способе. Теперь неплохо бы было написать код для БМакса и не объявлять дополнительный тип дублирующий класс из С-файла. 

SuperStrict

Import "c_test_002.cpp" ' цепляем cpp-файл.

Extern "C"

' объявляем С-класс
 Type myClass
  Method _pad1() 'padding for virtual destructors
  Method _pad2()
  Method HelloWorld:String()
  Method Hello:String( name:String )
 End Type

' экспортируем только функцию создания объекта класса
 Function create_obj_of_myClass:myClass()

End Extern

' создаем объект экспортного класса , экспортной функцией 
Local obj:myClass = create_obj_of_myClass()
If( Not obj ) Then Print "o_O"; end

' вызываем методы класса
Print obj.HelloWorld()
Print obj.Hello("dimanche")

end

Безусловно, этот метод проще чем первый. Методы _pad1() и _pad2() зарезервированы для виртуальных дестррукторов С-класса. Если их убрать, то неизбежна ошибка "Unhandled Memory Exception Error", но это то неудобство которое вполне можно потерпеть, чем писать функции обвязки для каждого метода класса :).

ЗАКЛЮЧЕНИЕ.

В заключении могу посоветовать еще кое-что. Експортируемую из С-функцию, можно обозвать так как вы сами того желаете, чтоб использовать ее в вашей БМакс программе. Делается это так, например вам не нравится моя_длинная_в_названии_функция (create_obj_of_myClass) , тогда при ее экспорте можно сделать так:

Extern

.................

Function create_myClass:myClass() = "create_obj_of_myClass"
.................

End Extern

то есть: ф-ция мое_название_функции() = "название_экспортируемой_фунции"

И далее в коде можно использовать уже ваше новое название. Заместо:

Local obj:myClass = create_obj_of_myClass()

теперь:

Local obj:myClass = create_myClass()

Вот в общем-то и всё, что я хотел вам рассказать. Спасибо за внимание. Разумная критика и предложения - приветствуются.

http://dimanche.ucoz.ru/CPP_tests.zip
Категория: BlitzMax | Добавил: dimanche (10.01.2009)
Просмотров: 1063 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Имя *:
Email *:
Код *:
Copyright MyCorp © 2024