SimpleINI library - can't compile a code with SI_NO_CONVERSION defined - c++

I use SimpleINI library on Linux. There is the following comment:
// Defines the conversion classes for different libraries. Before including
// SimpleIni.h, set the converter that you wish you use by defining one of the
// following symbols.
//
// SI_NO_CONVERSION Do not make the "W" wide character version of the
// library available. Only CSimpleIniA etc is defined.
// SI_CONVERT_GENERIC Use the Unicode reference conversion library in
// the accompanying files ConvertUTF.h/c
// SI_CONVERT_ICU Use the IBM ICU conversion library. Requires
// ICU headers on include path and icuuc.lib
// SI_CONVERT_WIN32 Use the Win32 API functions for conversion.
When I try to compile the following code:
#define SI_NO_CONVERSION
#include "SimpleIni.h"
int main()
{
CSimpleIni ini;
return 0;
}
I get the compilation error: ‘CSimpleIniA’ was not declared in this scope It looks like SI_NO_CONVERSION is not defined in SimpleIni.h. Could you explain what's going on ?

SimpleIni.h only defines SI_Case and SI_NoCase when either of SI_CONVERT_GENERIC, SI_CONVERT_ICU or SI_CONVERT_WIN32 is defined. This leaves SI_Case and SI_NoCase undefined when (only) SI_NO_CONVERSION is defined, which causes the CSimpleIniTempl template instantiation to fail, with the related compile errors. This is an oversight/bug in the library and should be reported to the author.
As a workaround, adding the missing definitions before #include "SimpleIni.h" gets the code to compile.
#define SI_NO_CONVERSION
#define SI_Case SI_GenericCase // ***
#define SI_NoCase SI_GenericNoCase // ***
#include "SimpleIni.h"
// ... etc ...

The doc you included says it all:
Only CSimpleIniA etc is defined [when SI_NO_CONVERSION is defined].
Below is an edited version of the first example in the README.md. The SI_ASSERT macro is defined in the header file but the ASSERT_EQ and ASSERT_STREQ macros, referenced in the example, are not. It's almost unforgivable that someone's examples don't compile.
As I mentioned in a comment, this is not a well-maintained project. The instructions for building and testing don't work in a very obvious way. Seems like the developer has files in his working copy that aren't in the git repository. Inexcusable.
Additionally, I get extra compilation errors when I define SI_NO_CONVERSION. Don't use this project. Use something else instead.
#include "SimpleIni.h"
int main () {
CSimpleIniA ini;
ini.SetUnicode();
SI_Error rc = ini.LoadFile("example.ini");
if (rc < 0) { /* handle error */ };
const char* pv;
pv = ini.GetValue("section", "key", "default");
ini.SetValue("section", "key", "newvalue");
pv = ini.GetValue("section", "key", "default");
}
You compile this with something like g++.

Related

C++ Thor library - problem with using resource loader class ( ' ' does not name a type)

I have been recently practicing managing multiple objects and drawing them in C++ using SFML library. I wanted my textures and future resources to be more reusable so I decided to make use of Thor library which suits my needs really well.
So I've written first few lines of code based on what you can find in this tutorial and the compiler always says:
main.cpp|12|error: 'textures_holder' does not name a type
This line gives an error :
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
I'm using Code::Blocks IDE with MinGW compiler and SFML 2.5.0.
Here's my main.cpp and the header file which contains extern object :
//...
#include <Thor/Resources.hpp>
#include "Dirt_Block.h"
using namespace std;
//Adding textures to the texture library
//THIS LINE GIVES AN ERROR
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
//Rest of code...
Dirt_Block.h (only the upper part) :
#ifndef DIRT_BLOCK_H
#define DIRT_BLOCK_H
#include <SFML\Graphics.hpp>
#include <vector>
#include <Thor/Resources.hpp>
#include <Thor/Resources/SfmlLoaders.hpp>
extern sf::Vector2u screenRes;
extern thor::ResourceHolder<sf::Texture, std::string> textures_holder;
//Rest of the code
I'd like to know what is causing this error and maybe help others who may experience similiar frustrating problems. Thanks for help.
EDIT :
As suggested in the comment I've declared a few extern int variables in the Dirt_Block.h so now it looks like this :
//...
extern int test_int_up;
extern sf::Vector2u screenRes;
extern thor::ResourceHolder<sf::Texture, std::string> textures_holder;
extern int test_int_d;
//...
And then assinged to them some value in main.cpp :
//...
test_int_up = 55;
test_int_d = 55;
//Adding textures to the texture library
textures_holder.acquire("Dirt", thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png"));
//...
But the compiler gives error :
main.cpp|9|error: 'test_int_up' does not name a type
main.cpp|10|error: 'test_int_d' does not name a type
main.cpp|12|error: 'textures_holder' does not name a type
Much less distracting to see what your problem is without all the extraneous code!
C++ programs don't start from the top of the file and run code down to the bottom. They start at the main(), and control flow proceeds from there, with one thing triggering another.
(Note: That doesn't take into account global constructor ordering, which does go in order of declaration--but you have no guarantee of the order declarations from "different files" might run in.)
Point being, you can't just make random function or method calls in the middle of a file. That's where you put declarations. You have to be inside of a function or method to make calls, e.g.
int main() {
textures_holder.acquire(
"Dirt",
thor::Resources::fromFile<sf::Texture>("Textures\\dirt_block.png")
);
...
}

Valac missing generated header

I have two files, client.vala and lib.vapi.
The VAPI defines a class (that would usually talk to C code):
class Toplevel.Sub.CClass
{
public uint i;
}
And client.vala uses the class:
class Toplevel.Sub.UserClass
{
public Toplevel.Sub.CClass c_class;
}
int main()
{
var cls = new Toplevel.Sub.UserClass();
cls.c_class.i = 0;
return 0;
}
When I attempt to compile the program, I get an error:
$ valac client.vala lib.vapi
/tmp/bug/client.vala.c:7:20: fatal error: client.h: No such file or directory
compilation terminated.
error: cc exited with status 256
Compilation failed: 1 error(s), 0 warning(s)
The compiler seems to want a header generated for the functions in client.vala.
Is this a bug or am I missing something?
You've discovered something I didn't know about the Vala compiler. client.h is the default C header name generated by the compiler when no alternative is provided. It has used the basename of the source Vala file. You can change this using the cheader_filename CCode detail. Change what you have in your VAPI to:
[CCode (cheader_filename = "my_real_c_header.h")]
class Toplevel.Sub.CClass
{
public uint i;
}
and you will see the include is now #include "my_real_c_header.h"
By the way if you compile with valac client.vala --vapididr . --pkg lib you will see the header is included as #include <my_real_c_header.h>. Personally I think VAPIs should be used with the --pkg option.
If you are literally using Toplevel.Sub.CClass to 'usually talk to C code' then you have misunderstood the purpose of a VAPI. I take 'talk to' to mean calling various C functions and collecting the results so they can be presented in a more Vala friendly way to the rest of your program. So it is a wrapper interface.
A VAPI contains instructions to the Vala compiler to translate names into the right names for the C interface. For example you might have a very simple C function, void top_level_do_something (), that you want to use in Vala. In Vala it helps to use a namespace so the VAPI could be:
[CCode (cheader_filename = "my_real_c_header.h")]
namespace TopLevel {
[CCode (cname = "top_level_do_something")]
public void do_something ();
}
You can then call this in Vala with TopLevel.do_something () and the compiler would write this out as top_level_do_something () in C.
Take a look at Writing a VAPI Manually for more details.

Warnings when compiling Boost libraries in C++ Builder

I am getting warnings when I am trying to include <boost/thread.hpp> in C++ Builder. For every unit I am including it, C++ Builder shows up these 2 lines:
thread_heap_alloc.hpp(59): W8128 Can't import a function being defined
thread_heap_alloc.hpp(69): W8128 Can't import a function being defined
Already tried some things, nothing worked though.
It compiles correctly, however, it's getting on my nerves. Why is this message being shown?
The lines are:
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
inline BOOST_THREAD_DECL void* allocate_raw_heap_memory(unsigned size)
{
void* const eap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
if(!heap_memory)
{
throw std::bad_alloc();
}
return heap_memory;
}
inline BOOST_THREAD_DECL void free_raw_heap_memory(void* heap_memory)
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
}
where 59 is the { below the BOOST_THREAD_DECL, as is 69. Looks like BOOST_THREAD_DECL is not defined properly or mis-defined, trying to follow through the Boost code is not that easy.
This is Boost 1.39.
add #define BOOST_THREAD_USE_LIB before including the thread.hpp.
This is what I tested:
#define BOOST_THREAD_USE_LIB
extern "C"
{
namespace boost
{
void tss_cleanup_implemented( void )
{
/*
This function's sole purpose is to cause a link error in cases where
automatic tss cleanup is not implemented by Boost.Threads as a
reminder that user code is responsible for calling the necessary
functions at the appropriate times (and for implementing an a
tss_cleanup_implemented() function to eliminate the linker's
missing symbol error).
If Boost.Threads later implements automatic tss cleanup in cases
where it currently doesn't (which is the plan), the duplicate
symbol error will warn the user that their custom solution is no
longer needed and can be removed.*/
}
}
}
#include <boost/thread.hpp>
Then set 'Link with Dynamic RTL' and 'Link with Runtime Packages'.
This does a clean build and starts a thread properly.

Neko Dlls in Haxe C++ target

I am trying to use Neko dlls (written in C++) with the C++ target of Haxe. I am able to call the functions in haxe but not able to pass values.
This is the C++ code -
value Hello(value h)
{
cout << val_int(h);
return val_int(1);
}DEFINE_PRIM(Hello, 1);
This is the Haxe code -
class Main
{
var load = cpp.Lib.loadLazy( "ndll" , "Hello", 1 );
static function main()
{
load(1);
}
}
It executes only if the function does not take parameters. Also, the value that is returned form the C++ function to Haxe is null.
This code actually works perfectly when I compile for the neko target, but it doesn't seem to work with the cpp target.
Any help is appreciated.
Here's the fully corrected C++ code :
#define IMPLEMENT_API
/* Will be compatible with Neko on desktop targets. */
#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX)
#define NEKO_COMPATIBLE
#endif
#include <hx/CFFI.h>
#include <stdio.h>
/* Your hello function. */
value hello(value h)
{
printf("%i\n", val_int(h));
return alloc_int(1);
}
DEFINE_PRIM(hello, 1);
/* Main entry point. */
extern "C" void mylib_main()
{
// Initialization code goes here
}
DEFINE_ENTRY_POINT(mylib_main);
What's important is that every value given as an argument to a primitive or returned by a primitive must be of the type value. That's why your parameter and return didn't work.
val_int is used to convert a value into a native C type, so your printing code was correct. But your return was wrong : you can't return a C int type when the function expects you to return a value to Haxe. You need to create a new Haxe Int type and return it. This is done with the help of alloc_int.
Here's the Haxe part of the code as a reference :
class Main
{
static var hello = cpp.Lib.load("myLib", "hello", 1);
static function main()
{
var myReturnedInt:Int = hello(1);
}
}
A few helpful links :
Neko C FFI
Neko FFI tutorial
CPP FFI notes
In order for this to work, you'll have to add to the header of your cpp file:
#define IMPLEMENT_API
#include <hx/CFFI.h>
(instead of neko's headers)
If you want the ndll to run on both neko and hxcpp, you should also add
#define NEKO_COMPATIBLE
before the hx/CFFI.h include.
You can compile using whatever is best for you, but I recommend using a Build.xml to generate your ndll, since it will automatically add the include and lib paths correctly for hxcpp's headers. You can see an example of a very simple Build.xml here:
http://pastebin.com/X9rFraYp
You can see more documentation about hxcpp's CFFI here: http://haxe.org/doc/cpp/ffi

cmath functions generating compiler error

I've written a small program that utilizes the Fast Light Toolkit and for some reason a compiler error is generated when trying to access the functions in the cmath header.
Such as error ::acos has not been declared.
This goes on for pretty much every function it tries to use in the header. What could I be missing?
The header files I have included are
Simple_window.h
Graph.h
both of which are part of the FLTK.
The code is this:
#include "Simple_window.h" // get access to our windows library
#include "Graph.h" // get access to graphics library facilities
int main()
{
using namespace Graph_lib; // our graphics facilities are in Graph_lib
Point tl(100,100); // to become top left corner of window
Simple_window win(tl,600,400,"Canvas"); // make a simple window
Polygon poly; // make a shape (a polygon)
poly.add(Point(300,200)); // add a point
poly.add(Point(350,100)); // add another point
poly.add(Point(400,200)); // add a third point
poly.set_color(Color::red); // adjust properties of poly
win.attach(poly); // connect poly to the window
win.wait_for_button(); // give control to display engine
}
Edit: Here is example code of when the compiler error is generated. This is inside the cmath header.
namespace std
{
// Forward declaration of a helper function. This really should be
// an `exported' forward declaration.
template<typename _Tp> _Tp __cmath_power(_Tp, unsigned int);
inline double
abs(double __x)
{ return __builtin_fabs(__x); }
inline float
abs(float __x)
{ return __builtin_fabsf(__x); }
inline long double
abs(long double __x)
{ return __builtin_fabsl(__x); }
using ::acos; //ERROR HERE
inline float
acos(float __x)
{ return __builtin_acosf(__x); }
inline long double
acos(long double __x)
{ return __builtin_acosl(__x); }
template<typename _Tp>
inline typename __enable_if<double, __is_integer<_Tp>::_M_type>::_M_type
acos(_Tp __x)
{
return __builtin_acos(__x);
}
Edit: Code::blocks is saving files as C files....
When you include the C++ version (<cXXXX>) of standard C libraries all the symbols are defined within the std namespace. In C++ you do not need to link against the math library (-lm is not required)
#include <cmath>
#include <iostream>
int main()
{
std::cout << std::fabs( -10.5 ) << std::endl;
}
I had this problem - it was driving me crazy but I tracked down the cause, and it was a little different than what I've seen reported on this issue.
In this case, the general cmath header (or math.h - the error and solution occur in C++ or C) had architectural environment switches to include architecture specific math subheaders. The architecture switch (environment variable) hadn't been defined, so it was punting and not actually including the headers that truly defined the math functions.
So there was indeed a single math.h or cmath.h, and it was included, but that wasn't enough to get the math functions. In my case, rather than define the architectural variable, I instead found the location of the correct sub math headers and added them to my compile path. Then the project worked!
This seems to be an issue that comes up a lot when porting Linux projects to OS-X. I'd imagine it might occur anytime a project was moved betwee platforms such that the standard library headers are arranged differently.
Jeff
Since your code as shown above does not directly call acos(), there is arguably a bug in one of the headers that you do use. It appears there is some (inline) code in one of the headers that invokes the acos() function without ensuring that the function is properly declared. This might be a macro or an inline function.
The best fix is to ensure that the headers are self-contained - change the headers.
If that is not possible, the hackaround is to include the appropriate header (#include <cmath>, probably) in the source code.
The program is able to access the cmath header, the error is in the cmath header itself.
In that case, you will probably need to provide a global acos() function (declaration at least, possibly definition too) that calls onto std::acos():
double acos(double x) { return std::acos(x); }
Just make sure this is not inside any namespace - not even the anonymous one. (Check compiled with G++ 4.0.1 on MacOS X, with '#include <cmath>' preceding it. Given that you have a problematic <cmath> header, you might need to get fancy:
extern double std::acos(double);
double acos(double x) { return std::acos(x); }
#include <cmath>
This is pretty nasty - are you sure there isn't a bug-fixed version of your compiler?
Is there any chance that you've got '#include <cmath>' inside a namespace?
It also happens in Visual C++, in programs that do not sapuse to use cmath.
I found that the problem is that I used main.c file instead of main.cpp file.
The error is most likely to be in your code and not in cmath... unless you changed something in cmath. Could you copy the errors and tell us what is the application you are using to program?