
У меня глобальных задач не было

Для того, чтобы опробовать свои силы, захотелось перетащить реализацию алгоритма кодирования длин серий (RLE

) с C# на C++ в ДЛЛку. Ну вот и упражняюсь

Если интересно, что получилось:
ДЛЛка:
Заголовок:
Код
#ifndef COMPRESS_H
#define COMPRESS_H
#define EXPORT extern "C" __declspec (dllexport)
EXPORT void* RLEEncode(const void* _data, const unsigned long _length);
EXPORT void* RLEDecode(const void* _data, const unsigned long _length);
void* BufferSet(void* _buff, unsigned char _byte, unsigned long _pos);
#endif
Реализация:
Код
#include <windows.h>
#include "Compress.h"
/// Точка входа в DLL.
bool APIENTRY DllMain(HINSTANCE _instance, DWORD _reason, LPVOID _reserved)
{
return true;
}
/// Функция производит сжатие указанных данных на основе алгоритма кодирования повторов.
EXPORT void* RLEEncode(const void* _data, const unsigned long _length)
{
unsigned long curDataPos;
unsigned long bufPos = 0;
unsigned char count = 1;
unsigned char curByte;
unsigned char nextByte;
void* retData = NULL;
for(curDataPos = 0; curDataPos < _length; curDataPos++)
{
curByte = ((unsigned char*) _data)[curDataPos];
nextByte = (curDataPos == _length - 1 ? ((unsigned char*) _data)[curDataPos - 1] : ((unsigned char*) _data)[curDataPos + 1]); // Если уже на границе массива, сравниваем с предыдущим
if(curByte == nextByte && count < 255 && curDataPos < _length - 1)
{
count++;
}
else
{
retData = BufferSet(retData, count, bufPos++); // Длина повтора
retData = BufferSet(retData, curByte, bufPos++); // Байт повтора
count = 1;
}
}
return retData;
}
/// Функция производит восстановление данных, сжатых на основе алгоритма кодирования повторов.
EXPORT void* RLEDecode(const void* _data, const unsigned long _length)
{
unsigned long curDataPos;
unsigned long bufPos = 0;
unsigned char count;
unsigned char curByte;
void* retData = NULL;
for(curDataPos = 0; curDataPos < _length; curDataPos += 2)
{
count = ((unsigned char*) _data)[curDataPos];
curByte = ((unsigned char*) _data)[curDataPos + 1];
while(count-- > 0)
{
retData = BufferSet(retData, curByte, bufPos++);
}
}
return retData;
}
/// Функция записывает в буфер указанный байт на указанную позицию.
void* BufferSet(void* _buff, unsigned char _byte, unsigned long _pos)
{
_buff = realloc(_buff, _pos + 2);
//if(_buff != NULL)
//{
((unsigned char*) (_buff))[_pos] = _byte;
((unsigned char*) (_buff))[_pos + 1] = '\0';
//}
return _buff;
}
Приложение:
Реализация:
Код
#include <stdio.h>
#include <windows.h>
typedef void* (*RLEEncode)(const void* _data, const unsigned long _length);
typedef void* (*RLEDecode)(const void* _data, const unsigned long _length);
/// Точка входа в приложение.
int main(int argc, char* argv[])
{
char* sTextToEncode = "AAABBCC";
void* buffer;
RLEEncode Encode;
RLEDecode Decode;
HINSTANCE compressDll = LoadLibrary("Compress.dll");
if(compressDll == NULL)
{
printf("ERROR: unable to load DLL!\n");
system("pause");
return 1;
}
Encode = (RLEEncode) GetProcAddress(compressDll, "RLEEncode");
Decode = (RLEDecode) GetProcAddress(compressDll, "RLEDecode");
if(Encode == NULL || Decode == NULL)
{
printf("ERROR: unable to find DLL functions!\n");
system("pause");
return 1;
}
buffer = Encode(sTextToEncode, 7);
printf("Encoded data: %s\n", (char*) buffer);
buffer = Decode(buffer, 6);
printf("Decoded data: %s\n", (char*) buffer);
free(buffer);
delete[] sTextToEncode;
FreeLibrary(compressDll);
system("pause");
return 0;
}
Вот сейчас хочется переделать фукнции в ДЛЛке, чтобы они сразу писали в указанный буфер, а не возвращали указатель на новый, ибо память утекает при вызове buffer = Encode(buffer, ...); - указатель на прежний ведь теряется

А как тут будет проще байт запихнуть-то? Можно, конечно, юзать STL класс vector (или stack

), но хотелось сделать это максимально "ручками"

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