Добрый день.
Вот тут такой вопрос назрел к участникам конференции.
Прошу прощения, если я ошибся форумом, но, как мне кажется,
мой вопрос относится к проектированию, а не к конкретному языку программирования.
В общем, ситуация такова:
У меня есть некоторые наработки в области обработки биологических сигналов.
Я бы хотел сделать библиотеку, что ей могли воспользоваться другие разработчики.
Хотелось бы поддерживать Visual C, C++ Builder и Delphi.
Сейчас все сделано на VC. Как мне сделать так, чтобы разрабатывать библиотеку на VC, а пользоваться ей могли на других языках ?
Здесь я вижу три пути:
1. Сделать COM компонент.
2. Сделать DLL.
3. Распространять в виде LIB файла и H файлов.
Насчет первого пункта все ясно. Тут можно пользоваться библиотекой из любого языка.
Насчет второго пункта:
В принципе, тоже ничего, но есть проблемы совместимости с другими языками.
(То есть, нельзя передавать классы в качестве параметров функций и т.д.)
Пункт три:
Тут совсем непонятно. Visual C имеет свой формат LIB файла, а C++ Builder -- другой. Конвертеров я пока что не нашел.
По идее, решение очевидно, это первый пункт. Но мне это не совсем нравится. Дело в том, что библиотечка будет небольшой и многие
не захотят тащить со своей программой лишние DLL/OCX. Можно ли обойтись созданием LIB файла, а потом его конвертить в другие форматы ?
Или же придется делать ActiveX ?
Спасибо.
А>Насчет второго пункта:
А>В принципе, тоже ничего, но есть проблемы совместимости с другими языками.
А>(То есть, нельзя передавать классы в качестве параметров функций и т.д.)
А почему бы не реализовать поведение классов в библиотеке, а саму структуру описать для каждого языка и при вызове вызывать соот. метод, описывающий нужное поведение. Передачу классов можно в dll реализовать через поинтер, а в описании класса на конечном языке использования установить контроль за передачей или что-то вроде...
С темой вроде "париться писать под каждый язык не охота" можно совладать использованием многоцелевых средств моделирования

... << RSDN@Home 1.1.3 stable >>
Здравствуйте, nayato, Вы писали:
А>>Насчет второго пункта:
А>>В принципе, тоже ничего, но есть проблемы совместимости с другими языками.
А>>(То есть, нельзя передавать классы в качестве параметров функций и т.д.)
N>А почему бы не реализовать поведение классов в библиотеке, а саму структуру описать для каждого языка и при вызове вызывать соот. метод, описывающий нужное поведение. Передачу классов можно в dll реализовать через поинтер, а в описании класса на конечном языке использования установить контроль за передачей или что-то вроде...
То есть, например, так:
есть функция DLLFunction, которая принимает параметр void *, а на конечном языке описать класс
class CClassForDLLFunction;
в котором будет одна из функций ExecDLLFunction(int a,int b);
И эта функция будет передавать функции DLLFunction структуру, в которой будут два параметра "a" и "b".
Примерно так ?
N>С темой вроде "париться писать под каждый язык не охота" можно совладать использованием многоцелевых средств моделирования 
А это как, поясните пожалуйста.
А>есть функция 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 >>
Если хочешь сделать все это без особого гемороя, можно сделать чуть проще:
в библиотеке реализуешь все классы. в среде использующей твою библиотеку нагло дублируешь структуру классов — такой 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 >>