From: Jules B. <ju...@je...> - 2008-03-29 11:05:03
|
So, I have successfully added some of the missing bindings that I needed. The code is so short that I embed it in this email. I'd be interested to hear any comments on the way I did this, and what you would want to change before committing it to wxhaskell. 1) Loading images from in-memory blocks Stub C++ file to bind to the appropriate wxImage constructor: #include "wx/wx.h" #include "wx/image.h" #include "wx/mstream.h" extern "C" { void * wxImage_CreateFromFileInMemory(void* data,int length,int type) { wxMemoryInputStream in(data,length); return (void*) new wxImage(in,type); } } You can compile this with "g++ -c `wx-config --cppflags` cstub.cpp" Then a haskell stub file to wrap a Ptr version of this and two bytestring versions: {-# OPTIONS -fglasgow-exts #-} module ImageExtras where import qualified Data.ByteString.Lazy as LB import qualified Data.ByteString as B import Foreign import Foreign.C import Graphics.UI.WXCore.WxcTypes import Graphics.UI.WXCore.WxcClassTypes imageCreateFromPtrFile :: Ptr b -> Int -> Int -> IO (Image ()) imageCreateFromPtrFile ptr len typ = withManagedObjectResult $ wxImage_CreateFromFileInMemory ptr (fromIntegral len) (fromIntegral typ) foreign import ccall "wxImage_CreateFromFileInMemory" wxImage_CreateFromFileInMemory :: Ptr b -> CInt -> CInt -> IO (Ptr (TImage ())) imageCreateFromLBytestringFile :: LB.ByteString -> Int -> IO (Image ()) imageCreateFromLBytestringFile bs typ = withArray (LB.unpack bs) $ \ptr -> imageCreateFromPtrFile ptr (fromIntegral $ LB.length bs) typ imageCreateFromBytestringFile :: B.ByteString -> Int -> IO (Image ()) imageCreateFromBytestringFile bs typ = withArray (B.unpack bs) $ \ptr -> imageCreateFromPtrFile ptr (B.length bs) typ I'm not sure if you can make these a bit more efficient by attacking the underlying bytestring rep, but I didn't try. It works, anyhow. I am able to load images from bytestreams (as it happens, the cover art from an M4A file). The magic invocation to get ghc to link it correctly seems to be: ghc --make main.hs cstub.o -lstdc++ `wx-config --libs` -optl -fexceptions 2) GetOption / SetOption for Images Slightly more fiddly. The C++ stub looks like this: #include "wx/wx.h" #include "wx/image.h" extern "C" { void wxImage_SetOption(void *_obj, void* key,void *value) { ((wxImage*)_obj)->SetOption((wxChar*)key,(wxChar*)value); } wxString* wxImage_GetOption(void *_obj, void* key) { return new wxString(((wxImage*)_obj)->GetOption((wxChar*)key)); } } (it took me quite a while to understand why casting to wxChar* works when the underlying type is WxString&; there is an implicit conversion because of a constructor) The haskell stub is this: {-# OPTIONS -fglasgow-exts #-} module ImageOptions where import Graphics.UI.WXCore.WxcTypes import Graphics.UI.WXCore.WxcClassTypes imageSetOption :: Image a -> String -> String -> IO () imageSetOption _obj key value = withObjectRef "imageSetOption" _obj $ \cobj -> withCWString key $ \cstr_key -> withCWString value $ \cstr_value -> wxImage_SetOption cobj cstr_key cstr_value foreign import ccall "wxImage_SetOption" wxImage_SetOption :: Ptr (TImage a) -> CWString -> CWString -> IO () imageGetOption :: Image a -> String -> IO String imageGetOption _obj key = withManagedStringResult $ withObjectRef "imageGetOption" _obj $ \cobj -> withCWString key $ \cstr_key -> wxImage_GetOption cobj cstr_key foreign import ccall "wxImage_GetOption" wxImage_GetOption :: Ptr (TImage a) -> CWString -> IO (Ptr (TWxString ())) 3) Points of confusion: For return types of type String, looking at the examples in elj*.cpp, why does it sometimes use copyStrToBuf to unpack the WxString on the C++ side in combination with withWStringResult on the haskell side, and other times just pass back the a freshly allocated WxString* from C++ in combination with withManagedStringResult? For arguments of object types, why do some bindings use withObjectPtr and some use withObjectRef? What's the EXWXEXPORT() macro for? It didn't seem very useful to me... Thanks, Jules |
From: Eric Y. K. <eri...@gm...> - 2008-03-29 14:29:21
|
Hi, By the way, if I haven't already mentioned this, there is a wxhaskell-devel that you may prefer to discuss this on. Personally, I'm happy either way. > The code is so short that I embed it in this email. I'd be interested > to hear any comments on the way I did this, and what you would want to > change before committing it to wxhaskell. Sorry, I can't offer much insight here. Hoping somebody else pipes up. Looking forward to your patch, in any case. > Then a haskell stub file to wrap a Ptr version of this and two > bytestring versions: Note that wxhaskell doesn't currently use the bytestring package. I guess this would be a pretty safe thing to add, since if I understand correctly, it's been around since GHC 6.6. On the other hand, unless we're willing to say that we only support GHC 6.8.2+, starting from wxhaskell 0.11 > It works, anyhow. I am able to load images from bytestreams (as it > happens, the cover art from an M4A file). The magic invocation to get > ghc to link it correctly seems to be: > > ghc --make main.hs cstub.o -lstdc++ `wx-config --libs` -optl -fexceptions I think that by rights, it should be possible to modify wxcore, so that the right linker flags get used when you use the wxcore package (e.g. with ghc --make) > For return types of type String, looking at the examples in elj*.cpp, > why does it sometimes use copyStrToBuf to unpack the WxString on the > C++ side in combination with withWStringResult on the haskell side, > and other times just pass back the a freshly allocated WxString* from > C++ in combination with withManagedStringResult? Not sure. In case you were curious, copyStrToBuf was something I had introduced in my Unicode patches to replace if (_buf) memcpy (_buf, result.c_str(), result.Length()); return result.Length(); The reason for doing it this way was quite simply that I had gotten sick of repeating if (dst) wxStrcpy ((wxChar*) dst, src.c_str()); return src.Length(); In any case, I guess it doesn't answer your question. I just wanted to point our that there isn't anything particularly special about this helper, which you probably realise anyway. > For arguments of object types, why do some bindings use withObjectPtr > and some use withObjectRef? I don't know. Anybody else? > What's the EXWXEXPORT() macro for? It didn't seem very useful to me... You meant EWXWEXPORT :-D Again, I do not know. I guess that you have also had a look at wxc/include/ewxw_def.h. Looking at it... #ifdef __WATCOMC__ #include <windows.h> #define EWXWEXPORT(TYPE,FUNC_NAME) TYPE __export __cdecl FUNC_NAME #else #ifdef _WIN32 #define EWXWEXPORT(TYPE,FUNC_NAME) __declspec(dllexport) TYPE __cdecl FUNC_NAME #undef EXPORT #define EXPORT extern "C" __declspec(dllexport) #else #define EWXWEXPORT(TYPE,FUNC_NAME) TYPE FUNC_NAME #endif #ifndef _cdecl #define _cdecl #endif #endif I get the impression that it's there for some kind of portability reasons. Will need to do research on this mysterious __declspec(dllexport), __cdecl and _cdecl business to understand better. Anyone already know what these do? I did not find any (relevant) instances of the string 'EWXW' in wxdirect, and thus surmise that (unlike TSelf), it is not used for generating the Haskell binding. One possibility is that it's just some vestigal code from the wxEiffel days, and isn't actually useful anymore. Sorry to be unhelpful :-/ -- Eric Kow <http://www.nltg.brighton.ac.uk/home/Eric.Kow> PGP Key ID: 08AC04F9 |
From: shelarcy <she...@gm...> - 2008-03-29 15:55:12
|
Hi, On Sat, 29 Mar 2008 23:29:08 +0900, Eric Y. Kow <eri...@gm...> wrote: >> What's the EXWXEXPORT() macro for? It didn't seem very useful to me... > > (snip) > > I get the impression that it's there for some kind of portability reasons. > Will need to do research on this mysterious __declspec(dllexport), __cdecl and > _cdecl business to understand better. Anyone already know what these do? __declspec(dllexport) is a calling convention to export functions in DLL, on Windows platform (Visual Studio). This convention's advantage is efficiency. http://msdn2.microsoft.com/en-us/library/3y1sfaz2(VS.80).aspx http://msdn2.microsoft.com/en-us/library/9h658af8(VS.80).aspx So, EXWXEXPORT is important for Windows user. Best Regards, -- shelarcy <shelarcy hotmail.co.jp> http://page.freett.com/shelarcy/ |
From: shelarcy <she...@gm...> - 2008-11-13 03:09:28
|
Hi Jules, I added your function with some changes (e.g. rename functions and use auto-generated haskell function instead of hardcode function) in the darcs repositoy. http://www.mail-archive.com/wxh...@li.../msg00304.html http://www.mail-archive.com/wxh...@li.../msg00322.html Please check these functions. If there is a bug in these functions, please send us tiny example. Because I want to fix that before wxhaskell 0.11 release when these functions have bug. Best regards, On Sat, 29 Mar 2008 20:04:55 +0900, Jules Bean <ju...@je...> wrote: > So, I have successfully added some of the missing bindings that I needed. > > The code is so short that I embed it in this email. I'd be interested > to hear any comments on the way I did this, and what you would want to > change before committing it to wxhaskell. > > 1) Loading images from in-memory blocks > > Stub C++ file to bind to the appropriate wxImage constructor: > > #include "wx/wx.h" > #include "wx/image.h" > #include "wx/mstream.h" > > extern "C" > { > void * wxImage_CreateFromFileInMemory(void* data,int length,int type) { > wxMemoryInputStream in(data,length); > return (void*) new wxImage(in,type); > } > } > > You can compile this with "g++ -c `wx-config --cppflags` cstub.cpp" > > Then a haskell stub file to wrap a Ptr version of this and two > bytestring versions: > > {-# OPTIONS -fglasgow-exts #-} > module ImageExtras where > > import qualified Data.ByteString.Lazy as LB > import qualified Data.ByteString as B > import Foreign > import Foreign.C > import Graphics.UI.WXCore.WxcTypes > import Graphics.UI.WXCore.WxcClassTypes > > imageCreateFromPtrFile :: Ptr b -> Int -> Int -> IO (Image ()) > imageCreateFromPtrFile ptr len typ > = withManagedObjectResult $ > wxImage_CreateFromFileInMemory ptr (fromIntegral len) (fromIntegral > typ) > foreign import ccall "wxImage_CreateFromFileInMemory" > wxImage_CreateFromFileInMemory :: Ptr b -> CInt -> CInt -> IO (Ptr > (TImage ())) > imageCreateFromLBytestringFile :: LB.ByteString -> Int -> IO (Image ()) > imageCreateFromLBytestringFile bs typ > = withArray (LB.unpack bs) $ \ptr -> > imageCreateFromPtrFile ptr (fromIntegral $ LB.length bs) typ > > imageCreateFromBytestringFile :: B.ByteString -> Int -> IO (Image ()) > imageCreateFromBytestringFile bs typ > = withArray (B.unpack bs) $ \ptr -> > imageCreateFromPtrFile ptr (B.length bs) typ > > I'm not sure if you can make these a bit more efficient by attacking > the underlying bytestring rep, but I didn't try. > > It works, anyhow. I am able to load images from bytestreams (as it > happens, the cover art from an M4A file). The magic invocation to get > ghc to link it correctly seems to be: > > ghc --make main.hs cstub.o -lstdc++ `wx-config --libs` -optl -fexceptions > > 2) GetOption / SetOption for Images > > Slightly more fiddly. The C++ stub looks like this: > > #include "wx/wx.h" > #include "wx/image.h" > > extern "C" > { > void wxImage_SetOption(void *_obj, void* key,void *value) { > ((wxImage*)_obj)->SetOption((wxChar*)key,(wxChar*)value); > } > wxString* wxImage_GetOption(void *_obj, void* key) { > return new wxString(((wxImage*)_obj)->GetOption((wxChar*)key)); > } > } > > (it took me quite a while to understand why casting to wxChar* works > when the underlying type is WxString&; there is an implicit conversion > because of a constructor) > > The haskell stub is this: > > {-# OPTIONS -fglasgow-exts #-} > module ImageOptions where > > import Graphics.UI.WXCore.WxcTypes > import Graphics.UI.WXCore.WxcClassTypes > > imageSetOption :: Image a -> String -> String -> IO () > imageSetOption _obj key value = > withObjectRef "imageSetOption" _obj $ \cobj -> > withCWString key $ \cstr_key -> > withCWString value $ \cstr_value -> > wxImage_SetOption cobj cstr_key cstr_value > foreign import ccall "wxImage_SetOption" wxImage_SetOption :: > Ptr (TImage a) -> CWString -> CWString -> IO () > > imageGetOption :: Image a -> String -> IO String > imageGetOption _obj key = > withManagedStringResult $ > withObjectRef "imageGetOption" _obj $ \cobj -> > withCWString key $ \cstr_key -> > wxImage_GetOption cobj cstr_key > foreign import ccall "wxImage_GetOption" wxImage_GetOption :: > Ptr (TImage a) -> CWString -> IO (Ptr (TWxString ())) > > > 3) Points of confusion: > > For return types of type String, looking at the examples in elj*.cpp, > why does it sometimes use copyStrToBuf to unpack the WxString on the > C++ side in combination with withWStringResult on the haskell side, > and other times just pass back the a freshly allocated WxString* from > C++ in combination with withManagedStringResult? > > For arguments of object types, why do some bindings use withObjectPtr > and some use withObjectRef? > > What's the EXWXEXPORT() macro for? It didn't seem very useful to me... -- shelarcy <shelarcy hotmail.co.jp> http://page.freett.com/shelarcy/ |