Prev: CHtmlView issues
Next: Can step over in VC on Vista
From: dom_perron on 14 Mar 2007 08:52 Hi, I developed a component in .net which I call from an MFC program. A .net function called in my c++ program return a safearray ** (wich is a byte [] in .net). This function convert a string of binary data base64 encoded in a array of byte[]. Here is my .NET implementation: byte[] GetDecodedImage(String i_innerText) { byte[] base64 = Convert.FromBase64String(i_innerText); return base64; } Here is the COM c++ implementation of this function: virtual HRESULT __stdcall GetDecodedImage (/*[out,retval]*/ SAFEARRAY * * pRetVal ) = 0; I want to create a cbitmap or a HBITMAP with the pointer of this struct but I dont know how to use it... Did someone could give me any idea? Thanks Dominique
From: MrAsm on 14 Mar 2007 11:18 On 14 Mar 2007 05:52:21 -0700, dom_perron(a)hotmail.com wrote: It's not clear to me if your array stores just bitmap pixel data in RGB (but, in this case, how do you know bitmap width and height? Is this information already known, or constant?), or if these are the bytes of a .bmp file (just copied into memory). Could you please clarify this? Moreover, I'm not sure about this point, but I think that you can call C# and other .NET managed stuff from C++ and MFC, enabling some Visual Studio .NET/2005 switch (/CLR?). In this way, you would avoid the pain of SAFEARRAY management... MrAsm >Hi, > >I developed a component in .net which I call from an MFC program. >A .net function called in my c++ program return a safearray ** (wich >is a byte [] in .net). This function convert a string of binary data >base64 encoded in a array of byte[]. > >Here is my .NET implementation: > >byte[] GetDecodedImage(String i_innerText) >{ >byte[] base64 = Convert.FromBase64String(i_innerText); > > return base64; >} > >Here is the COM c++ implementation of this function: > >virtual HRESULT __stdcall GetDecodedImage (/*[out,retval]*/ SAFEARRAY >* * pRetVal ) = 0; > >I want to create a cbitmap or a HBITMAP with the pointer of this >struct but I dont know how to use it... Did someone could give me any >idea? > >Thanks > >Dominique
From: dom_perron on 14 Mar 2007 11:43 On Mar 14, 11:18 am, MrAsm <m...(a)usa.com> wrote: > On 14 Mar 2007 05:52:21 -0700, dom_per...(a)hotmail.com wrote: > > It's not clear to me if your array stores just bitmap pixel data in > RGB (but, in this case, how do you know bitmap width and height? Is > this information already known, or constant?), or if these are the > bytes of a .bmp file (just copied into memory). > > Could you please clarify this? > > Moreover, I'm not sure about this point, but I think that you can call > C# and other .NET managed stuff from C++ and MFC, enabling some Visual > Studio .NET/2005 switch (/CLR?). > In this way, you would avoid the pain of SAFEARRAY management... > > MrAsm > > > > >Hi, > > >I developed a component in .net which I call from an MFC program. > >A .net function called in my c++ program return a safearray ** (wich > >is a byte [] in .net). This function convert a string of binary data > >base64 encoded in a array of byte[]. > > >Here is my .NET implementation: > > >byte[] GetDecodedImage(String i_innerText) > >{ > >byte[] base64 = Convert.FromBase64String(i_innerText); > > > return base64; > >} > > >Here is the COM c++ implementation of this function: > > >virtual HRESULT __stdcall GetDecodedImage (/*[out,retval]*/ SAFEARRAY > >* * pRetVal ) = 0; > > >I want to create a cbitmap or a HBITMAP with the pointer of this > >struct but I dont know how to use it... Did someone could give me any > >idea? > > >Thanks > > >Dominique- Hide quoted text - > > - Show quoted text - Do you know where I can find documentation on how I can call .NET component in an MFC ActiveX using /CLR? I am working with VS2003. Thanks Dominique
From: MrAsm on 14 Mar 2007 12:44 On 14 Mar 2007 08:43:17 -0700, dom_perron(a)hotmail.com wrote: >Do you know where I can find documentation on how I can call .NET >component in an MFC ActiveX using /CLR? I am working with VS2003. > >Thanks >Dominique Hi, sorry, but I don't know how to mix C++ and .NET stuff. (Frankly speaking, if I want to use .NET, I would use C# - a well designed language - and not what I consider an ugly "genetic-modified" :) C++ with managed .NET extensions: the so called "managed C++". And if I need communication between .NET managed world and native Win32 world, I would use simple C-interface DLLs or COM interop. But it's just IMHO.) However, if you have a pointer to the SAFEARRAY, and you want to use its data, this is how you might consider to do: <CODE> // SAFEARRAY * psa; HRESULT hr; BYTE * pBytes = NULL; // Get a pointer to the elements of the array hr = SafeArrayAccessData( psa, (void HUGEP**)&pBytes ); if (FAILED(hr)) // Error ... // *** Use the data pointed by pBytes *** .... .... // Release array SafeArrayUnaccessData( psa ); pBytes = NULL; </CODE> If your byte array is just a memory copy of a bitmap file, you may consider using the following function to create the bitmap from this data. It's just: HBITMAP hbmpMyImage = LoadBitmapFromMemory( pBytes ); (The routine uses ::CreateDIBSection.) Here's the code: <CODE> //------------------------------------------------------------------ // Load a DIB file from memory buffer. // Return bitmap handle on success, NULL on error // // by MrAsm //------------------------------------------------------------------ HBITMAP LoadBitmapFromMemory( void * pBmpFileData ) { // Check parameter ASSERT( pBmpFileData != NULL ); if ( pBmpFileData == NULL ) return NULL; // Pointer to file bytes BYTE * pFileBytes = (BYTE *)pBmpFileData; // DIB bits (will be set by CreateDIBSection) BYTE * pBits = NULL; // Access the BITMAPINFOHEADER section BITMAPINFOHEADER * pbmih = (BITMAPINFOHEADER *)(pFileBytes + sizeof(BITMAPFILEHEADER)); // Create the DIB HBITMAP hBitmap = ::CreateDIBSection( NULL, // No HDC used (BITMAPINFO *)pbmih, // Pointer to DIB information 0, // Default (void **)&pBits, // The function will return pointer to // bitmap bits NULL, // No file mapping 0 ); // No file mapping if ( hBitmap == NULL ) return NULL; // Get pointer to bitmap bits in original file // (we obtain the offset from BITMAPFILEHEADER.bfOffBits field) BITMAPFILEHEADER * pbmfh = (BITMAPFILEHEADER *)pFileBytes; BYTE * pSourceBitmapBits = pFileBytes + pbmfh->bfOffBits; // Copy bits memcpy(pBits, pSourceBitmapBits, pbmih->biSizeImage); // Return bitmap handle return hBitmap; } </CODE> Hope it helps, MrAsm
From: MrAsm on 14 Mar 2007 15:17 On 14 Mar 2007 08:43:17 -0700, dom_perron(a)hotmail.com wrote: >> >I developed a component in .net which I call from an MFC program. >> >A .net function called in my c++ program return a safearray ** (wich >> >is a byte [] in .net). This function convert a string of binary data >> >base64 encoded in a array of byte[]. >> >> >Here is my .NET implementation: >> >> >byte[] GetDecodedImage(String i_innerText) >> >{ >> >byte[] base64 = Convert.FromBase64String(i_innerText); >> >> > return base64; >> >} If you are using .NET just for the built-in base-64 decoding class, you might consider the following C++ code. I adapted the core decoding engine from a set of C functions at: http://www.fourmilab.ch/webtools/base64/ (they have a command line base64 decoder/encoder written in C.) If you have a base-64 encoded string, and you want to decode it, you can write e.g.: // Your base64 encoded input string: // std::string base64data; // Buffer to store result Base64Decoder::Buffer result; // Do the decoding BYTE * pBytes = Base64Decoder::Decode( base64data, result ); The Base64Decoder::Decode method takes in input the base64 encoded string, and a reference to a byte buffer. The method will decode the input data into the buffer, and will return a pointer to first buffer byte. Note that the buffer is a std::vector<BYTE> allocated onto the stack, so there's no need to delete[] the buffer. The code follows: <CODE File="Base64Decoder.h"> ////////////////////////////////////////////////////////////////////////// // FILE: Base64Decoder.h #pragma once // // *** Base-64 Decoder *** // // By MrAsm // class Base64Decoder { public: // Byte buffer typedef std::vector< BYTE > Buffer; // // NOTE: // Base-64 encoded strings are pure ASCII strings, // so they don't need Unicode, and can be stored // into std::string. // // Decode a base64-encoded string, and return the decoded string static std::string DecodeString( IN const std::string & encodedString ); // Decode a base64-encoded string, and save result into a buffer. // Return pointer to first buffer byte. static BYTE * Decode( IN const std::string & encodedString, OUT Buffer & out ); // Decode base64-encoded data read from file, and save result // into a buffer. // Return pointer to first buffer byte on success. // Return NULL on error. static BYTE * DecodeFile( IN LPCTSTR szFileName, OUT Buffer & out ); // // IMPLEMENTATION // private: static const std::string base64Chars; static bool IsBase64( IN unsigned char c ) { return (isalnum(c) || (c == '+') || (c == '/')); } static bool CompactLines( IN LPCTSTR szFileName, OUT std::string & data ); }; ////////////////////////////////////////////////////////////////////////// </CODE> <CODE File="Base64Decoder.cpp"> ////////////////////////////////////////////////////////////////////////// // FILE: Base64Decoder.cpp #include "StdAfx.h" #include "Base64Decoder.h" const std::string Base64Decoder::base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; std::string Base64Decoder::DecodeString( IN const std::string & encodedString ) { // // This decoding engine is adapted from: // // http://www.fourmilab.ch/webtools/base64/ // int in_len = (int) encodedString.size(); int i = 0; int j = 0; int in_ = 0; unsigned char char_array_4[4], char_array_3[3]; std::string ret; while (in_len-- && ( encodedString[in_] != '=') && IsBase64(encodedString[in_])) { char_array_4[i++] = encodedString[in_]; in_++; if (i ==4) { for (i = 0; i <4; i++) char_array_4[i] = (unsigned char) base64Chars.find(char_array_4[i]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (i = 0; (i < 3); i++) ret += char_array_3[i]; i = 0; } } if (i) { for (j = i; j <4; j++) char_array_4[j] = 0; for (j = 0; j <4; j++) char_array_4[j] = (unsigned char) base64Chars.find(char_array_4[j]); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; } return ret; } // Build a single line from Base64 file content bool Base64Decoder::CompactLines( IN LPCTSTR szFileName, OUT std::string & data ) { data.clear(); FILE * file = _tfopen( szFileName, _T("rt") ); if ( file == NULL ) return false; static const int maxLineChars = 100; char line[ maxLineChars + 1 ]; std::ostringstream os; while ( true ) { ZeroMemory( line, sizeof(line) ); if ( ! fgets( line, maxLineChars, file ) ) { break; } // Remove ending '\r\n' size_t len = strlen(line); if ( line[len-2] == '\r' ) line[len-2] = '\0'; // Add line os << std::string( line ); } fclose( file ); file = NULL; data = os.str(); return true; } BYTE * Base64Decoder::Decode( IN const std::string & encodedString, OUT Buffer & out ) { // Clear output buffer out.clear(); // std::string is a vector of bytes, so we can store // decoded stuff into it std::string decoded = DecodeString( encodedString ); // Copy the string content into destination buffer out.resize( decoded.length() ); BYTE * pOutput = &(*out.begin()); memcpy( pOutput, decoded.c_str(), decoded.length() ); // Return pointer to destination buffer return pOutput; } BYTE * Base64Decoder::DecodeFile( IN LPCTSTR szFileName, OUT std::vector<BYTE> & out ) { // Clear output buffer out.clear(); // Check file name ASSERT( szFileName != NULL ); if ( szFileName == NULL ) return NULL; // Compact input file lines into a single base64 string std::string base64data; if ( ! CompactLines( szFileName, base64data ) ) return NULL; // Decode into buffer return Decode( base64data, out ); } ////////////////////////////////////////////////////////////////////////// </CODE> MrAsm
|
Pages: 1 Prev: CHtmlView issues Next: Can step over in VC on Vista |