Вопрос по поводу поддержки нескольких языков
От: Аноним  
Дата: 23.03.05 07:53
Оценка:
Добрый день.

Вот тут такой вопрос назрел к участникам конференции.
Прошу прощения, если я ошибся форумом, но, как мне кажется,
мой вопрос относится к проектированию, а не к конкретному языку программирования.

В общем, ситуация такова:

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

Хотелось бы поддерживать Visual C, C++ Builder и Delphi.

Сейчас все сделано на VC. Как мне сделать так, чтобы разрабатывать библиотеку на VC, а пользоваться ей могли на других языках ?
Здесь я вижу три пути:

1. Сделать COM компонент.
2. Сделать DLL.
3. Распространять в виде LIB файла и H файлов.

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

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

Пункт три:
Тут совсем непонятно. Visual C имеет свой формат LIB файла, а C++ Builder -- другой. Конвертеров я пока что не нашел.

По идее, решение очевидно, это первый пункт. Но мне это не совсем нравится. Дело в том, что библиотечка будет небольшой и многие
не захотят тащить со своей программой лишние DLL/OCX. Можно ли обойтись созданием LIB файла, а потом его конвертить в другие форматы ?
Или же придется делать ActiveX ?

Спасибо.
Re: Вопрос по поводу поддержки нескольких языков
От: nayato Россия  
Дата: 23.03.05 18:18
Оценка:
А>Насчет второго пункта:
А>В принципе, тоже ничего, но есть проблемы совместимости с другими языками.
А>(То есть, нельзя передавать классы в качестве параметров функций и т.д.)

А почему бы не реализовать поведение классов в библиотеке, а саму структуру описать для каждого языка и при вызове вызывать соот. метод, описывающий нужное поведение. Передачу классов можно в dll реализовать через поинтер, а в описании класса на конечном языке использования установить контроль за передачей или что-то вроде...
С темой вроде "париться писать под каждый язык не охота" можно совладать использованием многоцелевых средств моделирования
... << RSDN@Home 1.1.3 stable >>
Re[2]: Вопрос по поводу поддержки нескольких языков
От: Аноним  
Дата: 24.03.05 07:56
Оценка:
Здравствуйте, nayato, Вы писали:

А>>Насчет второго пункта:

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

N>А почему бы не реализовать поведение классов в библиотеке, а саму структуру описать для каждого языка и при вызове вызывать соот. метод, описывающий нужное поведение. Передачу классов можно в dll реализовать через поинтер, а в описании класса на конечном языке использования установить контроль за передачей или что-то вроде...

То есть, например, так:

есть функция DLLFunction, которая принимает параметр void *, а на конечном языке описать класс

class CClassForDLLFunction;

в котором будет одна из функций ExecDLLFunction(int a,int b);

И эта функция будет передавать функции DLLFunction структуру, в которой будут два параметра "a" и "b".

Примерно так ?

N>С темой вроде "париться писать под каждый язык не охота" можно совладать использованием многоцелевых средств моделирования

А это как, поясните пожалуйста.
Re[3]: Вопрос по поводу поддержки нескольких языков
От: nayato Россия  
Дата: 25.03.05 19:15
Оценка:
А>есть функция DLLFunction, которая принимает параметр void *, а на конечном языке описать класс

А>class CClassForDLLFunction;


А>в котором будет одна из функций ExecDLLFunction(int a,int b);


А>И эта функция будет передавать функции DLLFunction структуру, в которой будут два параметра "a" и "b".


А>Примерно так ?

хм... ООП так ООП! Оперируем объектами.Опишем некоторый класс (пример из жизни ):
public class Matrix
{
    private double[,] fData;
    public Vector SolveByGausse(Vector atc) // solves system defined by the matrix using Absolute Term Column
    {
        return (Vector)DLLFuncSolveByGausse((void *)atc); // вроде так в c++  :shuffle: 
    }
    public int Summarize(int a, int b) { return DLLFuncSummarize(int a, int b); }
}


В случае простых функций, вроде "посчитать a+b" в библиотеке так и пишем int Summarize(int a, int b) { return a+b; }
В случае сложных (которые получают объект на входе) надо проверить на COM-совместимость используемых вами в библиотеке методов работы с такими вот классами+проверить на COM-совместимость целевых ООЯзыков. То есть в библиотеке нужно реализовать подобную (если не идентичную ) Классовую модель, но с готовой реализацией. То есть в методе DLLFuncSolveByGausse мы предполагаем, что нам передали объект класса Vector и нам нужно его обработать (в частности вызвать его функцию, например). Тогда нужно в библиотеке иметь COM-совместимую реализацию класса Vector и работать только с COM-совместимыми возможностями языка.
Вся эта "COM-совместимость" необходима, чтобы достичь взаимопонимания между разными языками. Все не COM-совместимые фичи языка скорее всего не будут поддерживаться в другом языке. Это не важно при реализации библиотеки (поскольку объекту класса Matrix абсолютно все равно, что делается внутри функции DLLFuncSummarize) до тех пор, пока мы не работаем с объектами, передаваемыми через параметр. Фактически такой объект создан в другой среде и вообще говоря структура его, хранимая в памяти, в целом отличается от той, которую бы имел объект класса, описанного на языке, на котором писалась библиотека. Но как правило современные ООЯ поддерживают некоторую совместимость, описываемую COM-технологией (современный ООЯ как правило способен работать с COM-компонентами) и называемую COM-совместимостью (это как правило размещение в памяти виртуальной таблицы по адресу объекта и кое-что еще). Этим и можно воспользоваться. В рассмотренном примере опасных мест два:
1) передаем параметром Vector. Значит в библиотеке работаем только с COM-совместимой частью объекта.
2) возвращаем Vector. Это еще хуже: это обязывает и в конечной реализации работать только с COM-совместимой частью возвращенного объекта.

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

N>>С темой вроде "париться писать под каждый язык не охота" можно совладать использованием многоцелевых средств моделирования

А>А это как, поясните пожалуйста.

Структуры будущих классов разработать один раз в каком-нибудь средстве проектирования, а оттуда уже (если средство хорошее) проводить генерацию кода для целевых сред.
... << RSDN@Home 1.1.3 stable >>
Re[4]: Вопрос по поводу поддержки нескольких языков
От: nayato Россия  
Дата: 26.03.05 00:50
Оценка:
Если хочешь сделать все это без особого гемороя, можно сделать чуть проще:
в библиотеке реализуешь все классы. в среде использующей твою библиотеку нагло дублируешь структуру классов — такой wrapper получается.
Вот пример.
[pascal]
// в библиотеке описываем классы. + и нормальная реализация
TVector = class
...
end;

TMatrix = class
private
....
public
constuctor Create(...);
function SolveByGausse(atc: TVector): TVector;
function Summarize(a,b: Integer): Integer;
end;

//описываешь DLLFunctions — враперы для классов — так:
function DLLFuncCreateMatrixObject(someparams...): Pointer;
begin
Result:=Pointer(TMatrix.Create(someparams));
end;

procedure DLLFuncFreeMatrixObject(obj: Pointer);
begin
TMatrix(obj).Free;
end;

funcion DLLFuncSolveByGausse(obj: Pointer; atc: Pointer): Pointer;
begin
Result:=Pointer(TMatrix(obj).SolveByGausse(TVector(atc)));
end;

function DLLFuncSummarize(obj: Pointer; a,b: Integer): Integer;
begin
Result:=TMatrix(obj).Summarize(a,b);
end;

// В среде, использующей библиотеку описываем наши
// классы (только "публичное" поведение!). + в качестве
// реализации подсовываем вызовы спец-функций из библиотеки:
TVector = class
private
fObj: Pointer;
public
...
constructor CreateResulted(_obj: Pointer);
property Obj: Pointer read fObj;
end;

TMatrix = class
private
fObj: Pointer;
public
constuctor Create(someparams...);
destructor Destroy; override;
function SolveByGausse(atc: TVector): TVector;
function Summarize(a,b: Integer): Integer;
property Obj: Pointer read fObj;
end;

impleentation

constructor TVector.CreateResulted(_obj: Pointer);
begin
fObj:=_obj;
end;

constructor TMatrix.Create(someparams...);
begin
fObj:=DLLFuncCreateMatrixObject(someparams...);
end;

destructor Destroy;
begin
DLLFuncFreeMatrixObject(fObj);
fObj:=nil;
end;

function TMatrix.SolveByGausse(atc: TVector): TVector;
begin
Result:=TVector.CreateResulted(DLLFuncSolveByGausse(fObj,atc.Obj));
end;

function TMatrix.Summarize(a,b: Integer): Integer;
begin
Result:=DLLFuncSummarize(fObj,a,b);
end;

[pascal]

Чтобы несильно заботиться о видимости Obj-свойства (где надо и где не надо), можно унести его описание в protected и все классы, имеющие методы, параметрами которых могут стать объекты DLL-хранимых классов описать как friendly, т.е. в одном unit'е (для Object Pascal) или namespace'е (для C разных). Вот.
... << RSDN@Home 1.1.3 stable >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.