i've been struggling to get libpng to work on my opengl c++ program. I am trying to load png's as textures. I have downloaded the libpng16 source code and built it using Visual Studio 2010. I have correctly linked the lib files and included the png.h file.
When I build my project, libpng prints "libpng error: read error" to my console and nothing else. I have tried all the solutions i've found on the internet including changing my runtime configurations on the libpng project to match my project that im using it on.
The error occurs at the png_read_png function:
FILE * file = fopen(filename,"r");
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING , NULL ,NULL , NULL );
if ( png_ptr == NULL )
{
printf ( "Could not initialize libPNG ’s read struct.\n" ) ;
exit(-1);
}
png_infop png_info_ptr = png_create_info_struct(png_ptr) ;
if ( png_info_ptr == NULL )
{
printf ("Could not initialize libPNG ’s info pointer.\n");
exit ( -1) ;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
printf ( "LibPNG encountered an error.\n" ) ;
png_destroy_read_struct(&png_ptr, &png_info_ptr ,NULL );
exit( -1);
}
png_init_io ( png_ptr , file );
png_read_png ( png_ptr , png_info_ptr , 0 , NULL ) ;
png_uint_32 png_width = 0;
png_uint_32 png_height = 0;
int bits = 0;
int colour_type = 0;
png_get_IHDR ( png_ptr , png_info_ptr , & png_width , & png_height ,& bits , & colour_type ,NULL , NULL , NULL );
const unsigned BITS_PER_BYTE = 8;
unsigned bytes_per_colour = (unsigned)bits/ BITS_PER_BYTE ;
unsigned colours_per_pixel;
if ( colour_type == PNG_COLOR_TYPE_RGB)
{
colours_per_pixel = 3;
}
else
{
printf ( " Colour types other than RGB are not supported." ) ;
exit ( -1) ;
}
printf ( "png_width = %d, png_height = %d , bits = %d, colour type = %d. \n" , png_width , png_height , bits , colour_type );
unsigned char * data = new unsigned char [ png_width * png_height * colours_per_pixel * bytes_per_colour];
png_bytepp row_pointers = png_get_rows ( png_ptr , png_info_ptr ) ;
unsigned index = 0;
for ( unsigned y = 0; y < png_height ; y ++)
{
unsigned x = 0;
while ( x < png_width * colours_per_pixel * bytes_per_colour) {
data [index++] = row_pointers [y][x++];
data [index++] = row_pointers [y][x++];
data [index++] = row_pointers [y][x++];
}
}
I have made sure that the correct filename is passed and I have tried multiple different PNG's
Any assistance with this will be appreciated
Thanks
On Windows you must open image files in binary mode, otherwise any occurance of a sequence of bytes, that could be interpreted as will be converted into a single . Right now you're opening the file in standard mode, which is text mode. You can open in binary mode, by adding a 'b' to the mode string, i.e.
FILE * file = fopen(filename,"rb");
Related
so, I encountered a little problem and I am kinda stuck.
Basically I am trying to pass the value of a string** in C-type form to a char* string
The code is as follows:
static int BuildDBListSql( std::string **SqlBuf,
const char* ColumnNames,
const char* TableNames,
const char* CmdText,
sUINT Mode)
{
int rtnval = sSUCCESS;
const char * testSql = ( Mode & 02 ) ? ColumnNames : CmdText;
if ( SU_DbControl::DbCreateTradeTempTables(testSql) != sSUCCESS )
{
sLogMessage("Problem with temporary table results", sLOG_ERROR, 0);
return( sERROR );
}
if ( Mode & 02 )
{
*SqlBuf = new std::string[strlen(ColumnNames) + SQL_MAX_SELECT*40];
*SqlBuf = &std::string(ColumnNames);
if ( !( Mode & 010 ) )
{
// Attach State/Retrieval SQL.
char* SqlBufcopy = (*SqlBuf)->c_str();
sSQLInsertStateAndRetrieval( sDbConvertMode( Mode ), SqlBufcopy);
}
}
// SQL fragments are being passed:
else
{
size_t sqlBufLength = 0;
if ( Mode & 010 )
{
sqlBufLength = strlen(ColumnNames) + strlen(TableNames) + strlen(CmdText) + SQL_MAX_SELECT;
*SqlBuf = new std::string[ sqlBufLength ];
//sprintf( *SqlBuf, "SELECT %s FROM %s %s ",
*SqlBuf = fmt::format("SELECT {} FROM {} {} ", ColumnNames, TableNames, CmdText); // ColumnNames, TableNames, CmdText );
}
else
{
std::string *sqlPtr = new char[strlen(CmdText) + 2*SQL_MAX_SELECT];
strcpy( sqlPtr, CmdText );
sSQLSpecializeWhereClause( TableNames, sqlPtr );
sqlBufLength = strlen(ColumnNames) + strlen(TableNames) + SQL_MAX_SELECT;
sqlBufLength += strchr(TableNames, ',') ? strlen(CmdText) : strlen(sqlPtr);
*SqlBuf = new char[ sqlBufLength ];
sprintf( *SqlBuf, "SELECT %s From %s %s",
ColumnNames,
TableNames,
strchr( TableNames, ',' ) ? CmdText : sqlPtr );
delete [] sqlPtr;
// Attach State/Retrieval SQL
rtnval = sSQLInsertStateAndRetrieval( sDbConvertMode( Mode ),
*SqlBuf );
}
}
if (Mode & 0100)
{
char * tempBuf = sEntitySQLToDbSQL(*SqlBuf);
if( tempBuf )
{
delete [] *SqlBuf;
*SqlBuf = new char[ strlen(tempBuf) + 1];
strcpy(*SqlBuf, tempBuf);
}
else
{
sLogMessage("Error in sEntitySQLToDbSQL", sLOG_ERROR, 0);
return( sERROR );
}
}
return rtnval;
}
i get this error when running the solution: related to this line of code char* SqlBufcopy = (*SqlBuf)->c_str();
left of '.c_str' must have class/struct/union, type is std::string**
I kinda understand that the error is there due to me trying to get a c-type string out of a pointer, but I dont know the correct syntax to do what i want to do.
I tried with
char *SqlBufcopy = *SqlBuf.c_str()
also with
char *SqlBufcopy = *SqlBuf->c_str()
and it didnt work, help pls
To fix the error you ask about, change char *SqlBufcopy = *SqlBuf.c_str(); to
char *SqlBufcopy = (*SqlBuf)->c_str();
Reason: SqlBuf is pointer to pointer (which makes no sense at all), so to get to the actual object, you need to dereference it twice.
I'm using C++ for Microsoft Word 2010 automation. When the user closes the application and my programm wants to use the previously obtained IDispatch interface, the programm crashes (unhandled exception). Simular VBA code in Excel gives an "Error 462: The remote server does not exist" error. How can I detect that the application has been closed by the user in a way Excel does.
#ifdef __NO_PRECOMPILED_HEADERS__
#include "generic/platformdefs.h"
#endif
#include "test_word.h"
/*
* Include the right atlbase.h (depends on the compiler)
*/
#include "compat/which_atlbase.h"
static OLECHAR FAR *VISIBLE =
{
OLESTR( "Visible" )
} ;
static OLECHAR FAR *QUIT =
{
OLESTR( "quit" )
} ;
static void
VarSetBool( VARIANT *v , BOOL value )
{
V_VT( v ) = VT_BOOL ;
V_BOOL( v ) = value ? VARIANT_TRUE : VARIANT_FALSE ;
}
static void
DispatchPropertyPut
(
CComPtr<IDispatch> dispatch ,
OLECHAR FAR *property ,
VARIANT *value
)
{
HRESULT status ;
DISPID dispid ,
propertyput ;
DISPPARAMS parameters ;
UINT n_argument_error;
VARIANT result ;
/*
* Get the dispatch id of the method and arguments to invoke
*/
status = dispatch->GetIDsOfNames( IID_NULL ,
&property ,
1 ,
LOCALE_USER_DEFAULT ,
&dispid ) ;
if( !SUCCEEDED( status ) )
{
throw( 1 ) ;
}
/*
* Initialize result
*/
VariantInit( &result ) ;
/*
* need to be able to take the address of this
*/
propertyput = DISPID_PROPERTYPUT ;
/*
* Setup the parameters
*/
parameters.cNamedArgs = 1 ;
parameters.rgdispidNamedArgs = &propertyput ;
parameters.cArgs = 1 ;
parameters.rgvarg = value ;
/*
* Get the object
*/
status = dispatch->Invoke( dispid ,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYPUT ,
¶meters ,
&result ,
0,
&n_argument_error ) ;
/*
* Cleanup result if any
*/
VariantClear( &result ) ;
/*
* Success ?
*/
if( !SUCCEEDED( status ) )
{
throw( 2 ) ;
}
}
static void
DispatchInvoke
(
CComPtr<IDispatch> dispatch ,
OLECHAR FAR *method
)
{
DISPID dispid ;
HRESULT status ;
DISPPARAMS parameters ;
status = dispatch->GetIDsOfNames( IID_NULL ,
&method ,
1 ,
LOCALE_USER_DEFAULT ,
&dispid ) ;
if( !SUCCEEDED( status ) )
{
throw( 3 ) ;
}
parameters.cNamedArgs = 0 ;
parameters.rgdispidNamedArgs = 0 ;
parameters.cArgs = 0 ;
parameters.rgvarg = 0 ;
status = dispatch->Invoke( dispid ,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD ,
¶meters ,
0 ,
0 ,
0 ) ;
if( !SUCCEEDED( status ) )
{
throw( 4 ) ;
}
}
void
test_word( int argc , char *argv[] , void *data )
{
CComPtr<IDispatch> word ;
VARIANT v ;
HRESULT hr ;
OleInitialize( NULL ) ;
try
{
/*
* The metrowerks compiler doesn't handle __uuidof()
*/
# ifdef __MWERKS__
hr = word.CoCreateInstance( OLESTR( "Word.Application" ) ,
IID_IDispatch ,
0 ,
CLSCTX_SERVER ) ;
# else
hr = word.CoCreateInstance( OLESTR( "Word.Application" ) ,
0 ,
CLSCTX_SERVER ) ;
# endif
if( !SUCCEEDED( hr ) )
{
throw( 6 ) ;
}
VariantInit( &v ) ;
VarSetBool( &v , TRUE ) ;
DispatchPropertyPut( word , VISIBLE , &v ) ;
DispatchInvoke( word , QUIT ) ;
VarSetBool( &v , FALSE ) ;
/*
* This will crash the application
*/
DispatchPropertyPut( word , VISIBLE , &v ) ;
}
catch( int where )
{
fprintf( stderr , "Exception caught %d\n" , where ) ;
}
word.Release() ;
OleUninitialize() ;
}
The excel vba macro looks like this:
Sub test_word()
Dim word As Object
Set word = CreateObject("word.application")
word.Visible = True
word.quit()
'
' Quit the word application before the next statement
' and you will get Error 462: The remote server does not exist
'
word.Visible = False
Set word = Nothing
End Sub
This is more of a comment, but comments are limited...it might work as a solution...
Well, generally you wouldn't do what you're doing. You must be setting a breakpoint before the second property put and at that point manually closing Word. Generally, you would capture events from Word and then when Word closed, you would receive notification and then know not to use your interface pointer any more. To protect against not catching events, I might suggest first creating the application to get an IUnknown pointer first. Then when you want to make a call to IDispatch, query for the IDispatch and then make the call, and then release the IDispatch.
When you first create with an IUnknown, it will create an in process handler IUnknown for you. On the first call to query for IDispatch, it will at that point actually start up Word. On subsequent calls to QI for IDispatch and then make the call, the handler may be smart enough to just gracefully fail if Word has been shut down--or it may not. But, I would start there...if you don't want to catch events.
The real proper way to get events from Word and look for the Closing or Closed events.
Wow... just looked at Word events. Looks like there is a Quit event but not a Closing or BeforeClosing event or anything like that. So, you'd want to catch the Quit event. After that, set a flag or release your IDispatch interface and never use it again.
Interesting. Is Word 2010 all patched up? I ran the following against Word 2016 (what I have installed). It's also using Visual Studio 2017 but should compile on any Visual C++ in the last 10 years:
#include <comdef.h>
#include <atlbase.h>
class COleInitialize
{
public:
COleInitialize()
{
OleInitialize(NULL);
}
~COleInitialize()
{
OleUninitialize();
}
};
int main(int argc, char* argv[])
{
COleInitialize _oleinit;
IUnknownPtr lpUnk;
lpUnk.CreateInstance(L"Word.Application");
CComDispatchDriver disp(lpUnk);
disp.PutPropertyByName(L"Visible", &_variant_t(VARIANT_TRUE));
MessageBox(NULL, "Close Word", "Prompt", MB_OK);
return 0;
}
I use the example Plugin.cpp from amibroker ADK. I make a directory 'ASCII' under the folder 'amibroker' and put all the data inside named *.AQI. But no data found in amibroker. Is there something I changed in function GetQuotesEx cause the problem?
PLUGINAPI int GetQuotesEx( LPCTSTR pszTicker, int nPeriodicity, int nLastValid, int nSize, struct Quotation *pQuotes, GQEContext *pContext )
{
char filename[256];
FILE* fh;
int iLines = 0;
// format path to the file (we are using relative path)
sprintf_s(filename, "ASCII\\%s.AQI", pszTicker);
// open file for reading
fopen_s(&fh, filename, "r");
// if file is successfully opened read it and fill quotation array
if (fh)
{
char line[ 256 ];
// read the line of text until the end of text
// but not more than array size provided by AmiBroker
while( fgets( line, sizeof( line ), fh ) && iLines < nSize )
{
// get array entry
struct Quotation *qt = &pQuotes[ iLines ];
char* pTmp = NULL;
// parse line contents: divide tokens separated by comma (strtok) and interpret values
// date and time first
int datenum = atoi( strtok_s( line, ",", &pTmp) ); // YYMMDD
int timenum = atoi( strtok_s( NULL, ",", &pTmp) ); // HHMM
// unpack datenum and timenum and store date/time
qt->DateTime.Date = 0; // make sure that date structure is intialized with zero
qt->DateTime.PackDate.Minute = timenum % 100;
qt->DateTime.PackDate.Hour = timenum / 100;
qt->DateTime.PackDate.Year = 2000 + datenum / 10000;
qt->DateTime.PackDate.Month = ( datenum / 100 ) % 100;
qt->DateTime.PackDate.Day = datenum % 100;
// now OHLC price fields
qt->Open = (float) atof( strtok_s( NULL, ",", &pTmp) );
qt->High = (float) atof( strtok_s( NULL, ",", &pTmp) );
qt->Low = (float) atof( strtok_s( NULL, ",", &pTmp) );
qt->Price = (float) atof( strtok_s( NULL, ",", &pTmp) ); // close price
// ... and Volume
qt->Volume = (float) atof( strtok_s( NULL, ",\n", &pTmp) );
iLines++;
}
// close the file once we are done
fclose( fh );
}
// return number of lines read which is equal to
// number of quotes
return iLines;
}
I have a weird error when trying to execute mysql_stmt_execute.
The flow goes:
I get the list of the tables in my database I am connecting. (catalog, schema and name)
For every table I'm getting the list of foreign keys, fields and indexes.
Everything goes good until I hit the table named performance_schema.events_stages_summary_by_account_by_event_name.
I get the error: Identifier name "events_stages_summary_by_account_by_event_name" is too long. The weird thing is that the name is not an identifier - it is a parameter to the query and it is less than 64 characters which is the identifier limit.
Below is the relevant code:
std::wstring query3 = L"SELECT kcu.column_name, kcu.ordinal_position, kcu.referenced_table_schema, kcu.referenced_table_name, kcu.referenced_column_name, rc.update_rule, rc.delete_rule FROM information_schema.key_column_usage kcu, information_schema.referential_constraints rc WHERE kcu.constraint_name = rc.constraint_name AND kcu.table_catalog = ? AND kcu.table_schema = ? AND kcu.table_name = ?;";
char *catalog_name = row[0] ? row[0] : NULL;
char *schema_name = row[1] ? row[1] : NULL;
char *table_name = row[2] ? row[2] : NULL;
MYSQL_BIND params[3];
unsigned long str_length1, str_length2, str_length3;
str_length1 = strlen( catalog_name ) * 2;
str_length2 = strlen( schema_name ) * 2;
str_length3 = strlen( table_name ) * 2;
str_data1 = new char[str_length1], str_data2 = new char[str_length2], str_data3 = new char[str_length3];
memset( str_data1, '\0', str_length1 );
memset( str_data2, '\0', str_length2 );
memset( str_data3, '\0', str_length3 );
memset( params, 0, sizeof( params ) );
strncpy( str_data1, catalog_name, str_length1 );
strncpy( str_data2, schema_name, str_length2 );
strncpy( str_data3, table_name, str_length3 );
params[0].buffer_type = MYSQL_TYPE_STRING;
params[0].buffer = (char *) str_data1;
params[0].buffer_length = strlen( str_data1 );
params[0].is_null = 0;
params[0].length = &str_length1;
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = (char *) str_data2;
params[1].buffer_length = strlen( str_data2 );
params[1].is_null = 0;
params[1].length = &str_length2;
params[2].buffer_type = MYSQL_TYPE_STRING;
params[2].buffer = (char *) str_data3;
params[2].buffer_length = strlen( str_data3 );
params[2].is_null = 0;
params[2].length = &str_length3;
if( mysql_stmt_bind_param( res1, params ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errorMsg.push_back( err );
result = 1;
break;
}
else
{
prepare_meta_result = mysql_stmt_result_metadata( res1 );
if( !prepare_meta_result )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errorMsg.push_back( err );
result = 1;
break;
}
else
{
if( mysql_stmt_execute( res1 ) )
{
std::wstring err = m_pimpl->m_myconv.from_bytes( mysql_stmt_error( res1 ) );
errorMsg.push_back( err );
result = 1;
break;
}
Could someone please shed some light on the error? I can probably try to skip this table but I'd prefer not to.
[EDIT]
mysql --version
mysql ver 14.14 Distrib 5.6.35, for Linux (x86+64) using Editine wrapper
[/EDIT]
Edit:
Seems that the code is indeed OK and the strncpy is OK. I mistakenly read that the allocation was twice the length of the string but the length was still only one length of the string.
The reason why you see that error is because you are using a string which is not null terminated. This is caused by the fact that strncpy does not null-terminate the string if it exceeds the given limit and the limit you use is the actual length of the string:
memset( str_data1, '\0', str_length1 );
strncpy( str_data1, catalog_name, str_length1 );
params[0].buffer_length = strlen( str_data1 );
A better way to do this would be to use either snprintf(3) that does null terminate the string or by using the std::string constructor that takes a const char* and a length as parameters.
In SendCompressedString(),
*passing the compressed data string as an i/p argument.
*Tried printing the whole compressed data in a console window.Can able to print it in the console window....
*Now i need to convert that whole data to Byte * and sizeof that data as an i/p argument to SendBytes()
bool NetOutputBuffer_c::SendCompressedString ( std::string sStr )
{
std::cout.write(sStr.c_str(), sStr.size());
SendInt ( sStr.size() );
return SendBytes ( sStr.c_str(), sStr.size() );
}
In SendBytes(),
Tried to print the pBuf data but can able to print only 5% of data...
what shall i need to do inorder to print the whole data?
bool NetOutputBuffer_c::SendBytes ( const void * pBuf, int iLen )
{
BYTE * pMy = (BYTE*)pBuf;
printf("pMy is %s\n",pMy);
while ( iLen>0 && !m_bError )
{
int iLeft = m_iBufferSize - ( m_pBufferPtr-m_pBuffer );
printf("iLeft is %d\n",iLeft);
if ( iLen<=iLeft )
{
printf("iLen is %d\n",iLen);
memcpy ( m_pBufferPtr, pMy, iLen );
printf("m_pBuffer is %s\n",(char*)m_pBufferPtr);
m_pBufferPtr += iLen;
break;
}
ResizeIf ( iLen );
}
return !m_bError;
}
Requirement::
In SendCompressedString(),
*Need to convert the whole data into Byte * and send it as an i/p argument to SendBytes()
*In SendBytes(),need to print all the data...
*Can someone please help me to achieve this?
Why are you doing the memcpy in a loop? That looks wrong to me. Here is the memcpy reference:
http://www.cplusplus.com/reference/cstring/memcpy/
So you just need to specify a source and destination pointer (address) and what size to copy. So your code should be:
bool NetOutputBuffer_c::SendBytes ( const void * pBuf, int iLen )
{
BYTE * pMy = (BYTE*)pBuf;
memcpy ( m_pBufferPtr, pMy, iLen );
}