Passing a structur to a DLL ???

BlitzMax Forums/BlitzMax Programming/Passing a structur to a DLL ???

Hi :) I'm trying to work with UNRAR.DLL but i have problem
to passing structur to a dll function, anybody can help me ?
because i become crazy with bmax incomplete doc ....

Here is the UNRAR SDK :
http://www.blitz3dfr.com/tempo/UnRARDLL.rar

Here is my test :
Incbin "unrar.dll"

Const DllName:String = "unrar.dll"
Local DllHandle = LoadLibraryA(DllName)

If DLLhandle = 0 Then
	Notify "Unable to initialize unrar.dll"
	End
EndIf

Const ERAR_END_ARCHIVE = 10
Const ERAR_NO_MEMORY = 11
Const ERAR_BAD_DATA = 12
Const ERAR_BAD_ARCHIVE = 13 
Const ERAR_UNKNOWN_FORMAT = 14
Const ERAR_EOPEN = 15 
Const ERAR_ECREATE = 16
Const ERAR_ECLOSE = 17 
Const ERAR_EREAD = 18 
Const ERAR_EWRITE = 19 
Const ERAR_SMALL_BUF = 20
Const RAR_OM_LIST = 0 
Const RAR_OM_EXTRACT = 1 
Const RAR_SKIP = 0
Const RAR_TEST = 1 
Const RAR_EXTRACT = 2 
Const RAR_VOL_ASK = 0
Const RAR_VOL_NOTIFY = 1

Global RARGetDllVersion()"Win32" = GetProcAddress(DllHandle,"RARGetDllVersion")
Global RAROpenArchive(Structur:Int Ptr)"Win32" = GetProcAddress(DllHandle,"RAROpenArchiveData")


Type RARHeaderData
	Field RAR_ArcName:String
	Field RAR_FileName:String
	Field RAR_flags:Long
	Field RAR_PackSize:Long
	Field RAR_UnpSize:Long
	Field RAR_HostOS:Long
	Field RAR_FileCRC:Long
	Field RAR_FileTime:Long
	Field RAR_UnpVer:Long
	Field RAR_Method:Long
	Field RAR_FileAttr:Long
	Field RAR_CmtBuf:String
	Field RAR_CmtBufSize:Long
	Field RAR_CmtSize:Long
	Field RAR_CmtState:Long
End Type

Type RAROpenArchiveData
	Field RAR_ArcName:String
	Field RAR_OpenMode:Long
	Field RAR_OpenResult:Long
	Field RAR_CmtBuf[0]
	Field RAR_CmtBufSize:Long
	Field RAR_CmtSize:Long
	Field RAR_CmtState:Long
End Type


Global A:RAROpenArchiveData=New RAROpenArchiveData
A.RAR_ArcName="unrar.rar"
A.RAR_OpenMode=RAR_OM_LIST
A.RAR_CmtBufSize=16384



Print "Version : "+RARGetDllVersion()

RAROpenArchive(Int Ptr(Byte Ptr(A)))


The UNRAR.H say that :
#ifndef _UNRAR_DLL_
#define _UNRAR_DLL_

#define ERAR_END_ARCHIVE     10
#define ERAR_NO_MEMORY       11
#define ERAR_BAD_DATA        12
#define ERAR_BAD_ARCHIVE     13
#define ERAR_UNKNOWN_FORMAT  14
#define ERAR_EOPEN           15
#define ERAR_ECREATE         16
#define ERAR_ECLOSE          17
#define ERAR_EREAD           18
#define ERAR_EWRITE          19
#define ERAR_SMALL_BUF       20
#define ERAR_UNKNOWN         21

#define RAR_OM_LIST           0
#define RAR_OM_EXTRACT        1

#define RAR_SKIP              0
#define RAR_TEST              1
#define RAR_EXTRACT           2

#define RAR_VOL_ASK           0
#define RAR_VOL_NOTIFY        1

#define RAR_DLL_VERSION       4

struct RARHeaderData
{
  char         ArcName[260];
  char         FileName[260];
  unsigned int Flags;
  unsigned int PackSize;
  unsigned int UnpSize;
  unsigned int HostOS;
  unsigned int FileCRC;
  unsigned int FileTime;
  unsigned int UnpVer;
  unsigned int Method;
  unsigned int FileAttr;
  char         *CmtBuf;
  unsigned int CmtBufSize;
  unsigned int CmtSize;
  unsigned int CmtState;
};


struct RARHeaderDataEx
{
  char         ArcName[1024];
  wchar_t      ArcNameW[1024];
  char         FileName[1024];
  wchar_t      FileNameW[1024];
  unsigned int Flags;
  unsigned int PackSize;
  unsigned int PackSizeHigh;
  unsigned int UnpSize;
  unsigned int UnpSizeHigh;
  unsigned int HostOS;

  unsigned int FileCRC;
  unsigned int FileTime;
  unsigned int UnpVer;
  unsigned int Method;
  unsigned int FileAttr;
  char         *CmtBuf;
  unsigned int CmtBufSize;
  unsigned int CmtSize;
  unsigned int CmtState;
  unsigned int Reserved[1024];
};


struct RAROpenArchiveData
{
  char         *ArcName;
  unsigned int OpenMode;
  unsigned int OpenResult;
  char         *CmtBuf;
  unsigned int CmtBufSize;
  unsigned int CmtSize;
  unsigned int CmtState;
};

struct RAROpenArchiveDataEx
{
  char         *ArcName;
  wchar_t      *ArcNameW;
  unsigned int OpenMode;
  unsigned int OpenResult;
  char         *CmtBuf;
  unsigned int CmtBufSize;
  unsigned int CmtSize;
  unsigned int CmtState;
  unsigned int Flags;
  unsigned int Reserved[32];
};

enum UNRARCALLBACK_MESSAGES {
  UCM_CHANGEVOLUME,UCM_PROCESSDATA,UCM_NEEDPASSWORD
};

typedef int (CALLBACK *UNRARCALLBACK)(UINT msg,LONG UserData,LONG P1,LONG P2);

typedef int (PASCAL *CHANGEVOLPROC)(char *ArcName,int Mode);
typedef int (PASCAL *PROCESSDATAPROC)(unsigned char *Addr,int Size);

#ifdef __cplusplus
extern "C" {
#endif

HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *ArchiveData);
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *ArchiveData);
int    PASCAL RARCloseArchive(HANDLE hArcData);
int    PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *HeaderData);
int    PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
int    PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
int    PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar_t *DestPath,wchar_t *DestName);
void   PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LONG UserData);
void   PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc);
void   PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc);
void   PASCAL RARSetPassword(HANDLE hArcData,char *Password);
int    PASCAL RARGetDllVersion();

#ifdef __cplusplus
}
#endif

#endif


The data structures in the header are not going to be easy to deal with directly from BlitzMax due to the char arrays for the file and archive names. Its possible but it will be a mess.

You will have easier time to create a simple "C" wrapper that can create calls that will interface easier with BMAX over the DLL interface for dealing with the header structure.

Doug Stastny

Hum its a good idea ! but i'm not a C++ coder :( snif

unrar.bmx

Strict

Import "unrar.a"

Const ERAR_END_ARCHIVE    = 10
Const ERAR_NO_MEMORY      = 11
Const ERAR_BAD_DATA       = 12
Const ERAR_BAD_ARCHIVE    = 13
Const ERAR_UNKNOWN_FORMAT = 14
Const ERAR_EOPEN          = 15
Const ERAR_ECREATE        = 16
Const ERAR_ECLOSE         = 17
Const ERAR_EREAD          = 18
Const ERAR_EWRITE         = 19
Const ERAR_SMALL_BUF      = 20
Const ERAR_UNKNOWN        = 21

Const RAR_OM_LIST         = 0
Const RAR_OM_EXTRACT      = 1

Const RAR_SKIP            = 0
Const RAR_TEST            = 1
Const RAR_EXTRACT         = 2

Const RAR_VOL_ASK         = 0
Const RAR_VOL_NOTIFY      = 1

Const RAR_DLL_VERSION     = 4


Type RARHeaderData
	Field ArcName:Byte Ptr
	Field FileName:Byte Ptr
	Field Flags
	Field PackSize
	Field UnpSize
	Field HostOS
	Field FileCRC
	Field FileTime
	Field UnpVer
	Field Method_
	Field FileAttr
	Field CmtBuf:Byte Ptr
	Field CmtBufSize
	Field CmtSize
	Field CmtState
End Type

Type RARHeaderDataEx
	Field ArcName[1024]
	Field ArcNameW[1024]
	Field FileName[1024]
	Field FileNameW[1024]
	Field Flags
	Field PackSize
	Field PackSizeHigh
	Field UnpSize
	Field UnpSizeHigh
	Field HostOS
	
	Field FileCRC
	Field FileTime
	Field UnpVer
	Field Method_
	Field FileAttr
	Field CmtBuf:Byte Ptr
	Field CmtBufSize
	Field CmtSize
	Field CmtState
	Field Reserved[1024]
End Type

Type RAROpenArchiveData
	Field ArcName:Byte Ptr
	Field OpenMode
	Field OpenResult
	Field CmtBuf:Byte Ptr
	Field CmtBufSize
	Field CmtSize
	Field CmtState
End Type

Type RAROpenArchiveDataEx
	Field ArcName:Byte Ptr
	Field ArcNameW:Byte Ptr
	Field OpenMode
	Field OpenResult
	Field CmtBuf:Byte Ptr
	Field CmtBufSize
	Field CmtSize
	Field CmtState
	Field Flags
	Field Reserved[32]
End Type


Const UCM_CHANGEVOLUME=0,UCM_PROCESSDATA=1,UCM_NEEDPASSWORD=2

Extern
	Function RARCloseArchive(hArcData)
	Function RARGetDllVersion()
	Function RAROpenArchive(ArchiveData:RAROpenArchiveData)
	Function RAROpenArchiveEx(ArchiveData:RAROpenArchiveDataEx)
	Function RARProcessFile(hArcData,Operation,DestPath$z,DestName$z)
	Function RARProcessFileW(hArcData,Operation,DestPath$w,DestName$w)
	Function RARReadHeader(hArcData,HeaderData:RARHeaderData)
	Function RARReadHeaderEx(hArcData,HeaderData:RARHeaderDataEx)
	Function RARSetCallback(hArcData,Callback(msg,UserData,P1,P2),UserData)
	Function RARSetChangeVolProc(hArcData,ChangeVolProc(ArcName$z,Mode))
	Function RARSetPassword(hArcData,Password$z)
	Function RARSetProcessDataProc(hArcData,ProcessDataProc(Addr$z,Size))
End Extern


not sure if it works but it did compile and run your example.

to make unrar.a, run this batch file in the folder with unrar.dll. However, you need to have MinGW installed.
pexports unrar.dll >unrar.def
dlltool -d unrar.def -l unrar.a


If still need a C++ wrapper, I'd be happy to write you one.

The types wont work, blitzmax does not handle arrays the same way as C/C++

struct Foo {
  char Name[4]
}


in max needs to be like this

Type Foo
  Field Name_1:Byte
  Field Name_2:Byte
  Field Name_3:Byte
  Field Name_4:Byte
End Type


Since this has [1024] size of the names that is a mess. Really needs simple C Callable wrapper passing the names and returning handles to the underlying structures.


Doug Stastny

It definitely needs a wrapper. Unless BRL would like to kindly give us C-Compatible Structs? Pretty please?

Many thanks for reply guys ! i'll try tomorow :)