Вот вчера вечером ковырялся в с--, потихоньку начинаю раздуплять сие творение Свинкса, вобщем понял что пока буду писать на нем - ИМХО оптимизация сносная да и размеры скомпиленных приложений маленькие... да и удобнее для моих задач (в планее ООП)...
вот какие идеи (и наброски) у меня возникли:
щас правда пока в длл я пихал одну функцию, поэтому мои соображения по поводу нескольхих функций в длл выложу ниже...
итак, что мы имеем...
вид ддл который я делал был на асме такой
Code: Select all
use32
;begin proc
;допустим всеголишь надо отрисовать точечку на экране
mov eax,1
mov ebx,100
mov ecx,100
mov edx,0
int 0x40
ret
;end proc i dll
компилируем это безобразие в FASM - получаем файл размером 23 байта (или 24 я не помню уже... но это не столь важно)...
назовём его test.dll для начала... и скопируем его на /HD/1/test.dll (я так делал, хотя с загрузкой в эмуляции оходу запарка)
итак, длл пробная есть...
теперь прога которая её будет юзать, в ней как раз рассмотрен прототип механизма работы с длл (конечно он не ходится для оптимальной работы да ещё и без страничной памяти но на первое время я думаю прокатит)
Code: Select all
;dll_test.c--
#include "mclib2.h--"
;юзаются гуи контролы от Ивана Поддубного (респект за идею, у меня что то подобного в голове кружилось но на асме я так и не допер его сделать)
CMainWindow wnd;
struct TFile
{
dword Func,Blocks,Advanced,Buffer,OsMem;
char FileName[128];
};
TFile fileinfo;
fileinfo={8,1,1,#buffer,#osmem};
byte osmem[4096];
dword buffer; //указатель на адрес, куда будет загружена длл
void main()
{
fileinfo.FileName="/HD/1/test.dll",0; //правда я не понял почему компилер выдает ошибку здесь?
wnd.CMainWindow(... параметры); отрисовываем окошко
;теперь надо загрузить файл с длл, получить его размер
;кстати как узнать размер файла я не знаю, если есть идеи дайте знать
; //допустим получили размер файла
fileinfo.Buffer=MALLOC(GetFileSize(#fileinfo));
sys_tree_access(#fileinfo); //загружаем его в память
EBX=#buffer; // в ebx загружаем адрес процедуры из ддл
if(EBX){ //если либа загружена (адрес не равен нулю)
$call EBX //то передаем управление по этому адресу
}
FREE(#buffer); //выгружаем функцию
wnd.MainLoop(); //отрисовываем окно и отлавливаем события
}
в результате получаем
загружаем кусок кода и test.dll в память размером sizeof(test.dll) и по адресу #buffer, передаем управление (загоняем в IP регистр адрес следующей команды на #buffer+0 {неявно вызовом CALL EBX} ... выполнение идёт по этому адресу до коменды ret (#buffer+sizeof(test.dll)-1 т.е. на коде 0xC3) и возвращается к адресу следующему за этой процедурой...
далее осовбождаем память из под длл (если необходимо... или перед завершением работы программы)...
вот и всё... это конечно тривиальный простейший случай, к тому же параметры в функцию не передаются....
но рабочий... (проверено, тока размер файла вручную пришлось вбивать

)
на счёт передачи параметров даже ещё нет понятия
насчёт нескольких функций логично сделать заголовок файла длл, в котором будут находться названия процедр и их адреса что то типа такого
Code: Select all
;DLL HEADER
db 'MDLL'; header
dw 0001 ; header version для будущего.. (разные типы либов будет)
dd _DLL_Proc ; адрес списка процедур
dw _DLL_Count; количество процедур в списке
; поэтому можно будет обращаться как по индексу 0 .. Count-1 так и по названию функции
struc _DLLproc
{
.ProcName db ? имя процедуры типа 'PutPixelProc',0 ASCIIZ
.ProcAddr dd ? адрес процедуры
; .Params ? <-может и список параметров процедуры??? пока без параметров... но всё будет
}
теперь определяем таблицу
чтото типа такого
создаем массив типа
_DLL_Proc: //ссылка заголовка на массив
_DLLproc
типа такого .. (а вообще надо написать макрос, который будет сам всё это делать)
_DLLproc[0].ProcName='SetPixel';
_DLLproc[0].ProcAddr=SetPixel;
_DLLproc[1].ProcName='WriteText';
_DLLproc[1].ProcAddr=WriteText;
...
и так далее, незабыв в заголовок записать размер массива!
SetPixel:
..../// some code
ret
WriteText:
...// some code
ret
всё это дело компилируем
а в проге (или ядре) загружаем так к пирмеру
DllHandle=LoadDll('/hd/1/test.dll');
SPixel=GetProcAddrByName(DllHandle,'SetPixel');
if(SPixel) $call @SPixel; где @ - адрес (для удобства предствления .. не более, не путать с метками, это я для наглядности)
WText=GetProcAddrByIndex(DLLHandle,1);
if(WText) $call @WText;
...
ваши мнения?...
ебстественно лучше что бы это реализовано было в ядре а адрес Dll передавался через IPC например...