C++ problems with string - c++

I am doing some arduino development using cpp and h files and I am having some troubles using string with them. Currently I have
#include <string>
at the top of both the cpp and the h file. When I do that it gives me the error:
string: no such file or directory
If I go into the h file and change it to
#include <string.h>
then it gives me the error:
std::string has not been declared
Anytime I use the string I use: std::string to declare it. I am not using namespace std and these files were working together fine before I started to try to use string. I am new to C/C++ so I appreciate any help. Thanks!

In short, there is a way to use std::string with the Arduino.
TL;DR:
link to the arduino STLv1.1.2
NOTE
Please note that currently the harrdwareserialstream class provided by this STL should be considered broken (as per my testing, with version 1.6.5 of the IDE, and possibly anything after 1.0.6). therefore, you can't use
hardwareserialstream << "Hi there person number " << (int)i
and so on. it seems to no longer work due to taking a reference to the serial port it would interact with rather than a pointer - in short, continue using
Serial.print("Hi there person number");
Serial.print((int)i);
Lastly the serial classes don't know what a std::string is, so if using them, give it std::string.c_str() instead
Background
As McEricSir says in the comments, the arduino does provide its own string class, though i have found it to have problems related to memory leakage, which eventually ate all of the memory i had and the program stopped running - though this was in the arduino IDE v 1.0.5, it may have been fixed since then.
I had the same problem, and found someone who had created a version of the STL for the arduino (props to Andy Brown for this) which is a cutdown version of the SGI STL. it provides std::string, std::vector and a large amount of the STL to the arduino.
there are some things to be aware when using it though; if you have a board with very little memory, you will fill it quite quickly using the smart containers and other advanced features.
Using the Library
To use the library, you'll need to read the article, though I'll summarise the main points for you here:
Installation
simply extract the library to (assuming you are using the standard Arduino IDE) hardware\tools\avr\avr\include folder and you are good to go.
Using It
To actually use the new libraries, you need to include 2 additional things as well as the library you wanted.
firstly, you need to include the header iterator BEFORE any libraries that come from this STL - and in every file you reference the STL in.
Secondly, you also need to include the file pnew.cpp to provide an implementation of the new operator for the STL to work with.
Lastly, include any header files as you would normally.
to make use of the types gained from them, don't forget the the std:: namespace notation for them. (std::string and so on)
Bugs with it
Since Andy posted the library, there have been two bugs (that i'm aware of).
The first one Andy himself rectifies and explain in the blog post:
The compiler will spit out a typically cryptic succession of template errors, with the key error being this one:
dependent-name std::basic_string::size_type is parsed as a non-type,
but instantiation yields a type c:/program files (x86)/arduino-1.0/
hardware/tools/avr/lib/gcc/../../avr/include/string:1106: note:
say typename std::basic_string::size_type if a type is meant
Basically the STL was written a long time ago when C++ compilers were a little more forgiving around dependent types inherited from templates. These days they are rightly more strict and you are forced to explicitly say that you mean a type using the typename keyword.
Additionally, he provides the updated version for you to grab.
Lastly, there are reports in the comments about a bug in the newer versions of the IDE pertaining to the vector class where the compiler complains about the use of _M_deallocate without a prepending this->, which you can fix if you search for them inside the vector class
For your convenience
As i use this quite frequently, i've packaged up the current version, which can be found here (this includes both the fixes i have commented on)
Lastly
When using this, make sure to keep an eye on your free memory, and to that end i recommend the excellent class MemoryFree Library found here
on a side note if you #include<string> inside the header you won't need to include it in the relevant .cpp file

Related

std::string is different when passed to method

I'm using an external library (Qpid Proton C++) in my Visual Studio project.
The API includes a method like:
container::connect(const std::string &url) {...}
I call it in my code this way:
container.connect("127.0.0.1");
but when debugging, stepping into the library's function, the string gets interpreted in the wrong way, with a size of some millions chars, and unintelligible content.
What could be the cause for this?
You need to put the breakpoint inside the function and not at the function declaration level, where the variable exists but is not yet initialized.
Just in case someone runs into a similar problem, as Alan Birtles was mentioning in his comment, one possible cause is having the library and your code using different C++ runtimes, and that turned out to be the case this time.
In general, as stated in this page from Visual C++ documentation,
If you're using CRT (C Runtime) or STL (Standard Template Library) types, don't pass them between binaries (including DLLs) that were compiled by using different versions of the compiler.
which is exactly what was going on.

Is it possible to create a user-defined datatype in a language like C/C++(or maybe any) from a string as user input or from file

Well this might be a very weird question but my curiosity has striken pretty hard on this. So here it goes...
NOTE: Lets take the language C into consideration here.
As programmers we usually define a user-defined datatype(say struct) in the source code with the appropriate name.
Suppose I have a program in which I have a structure defined as:
struct Animal {
char *name;
int lifeSpan;
};
And also I have started the execution of this program.
Now, my question here is;
What if I want to define a new structure called "Plant" just like "Animal" mentioned above in my program, without writing its definition in the source code itself(which is obviously impossible currently) but rather from a user input string(or a file input) during runtime.
Lets say my program takes input string from a text file named file1.txt whose content is:
struct Plant {
char *name;
int lifeSpan;
};
What I want now is to have a new structure named "Plant" in my program which is already in execution. The program should read the file content and create a structure as written in the file and attach it to itself on-the-go.
I have checked out a solution for C++ in the discussion Declaring a data type dynamically in C++ but it doesnt seem to have a very convincing solution.
The solution I am looking for is at the compiler-linker-loader level rather than from the language itself.I would be very pleased and thankful if anyone is looking forward to sharing their ideas on this.
What you're asking about is basically "can we implement C as a scripting language?", since this is the only way code can be executed after compilation.
I'm aware that people have been writing (mostly in the comments) that it's possible in other languages but isn't possible in C, since C is a compiled language (hence data types should be defined during compile time).
However, to the best of my knowledge it's actually possible (and might not be as hard as one would imagine).
There are many possible approaches (machine code emulation (VM), JIT compilation, etc').
One approach will use a C compiler to compile the C script as an external dynamic library (.dll on windows, .so on linux, etc') and than "load" the compiled library and execute the code (this is pretty much the JIT compilation approach, for lazy people).
EDIT:
As mentioned in the comments, by using this approach, the new type is loaded as part of an external library.
The original code won't know about this new type, only the new code (or library) will be "aware" of this new type and able to properly use it.
On the other hand, I'm not sure why you're insisting on the need to use static types and a compiler-linker-loader level solution.
The language itself (the C language) can manage this task dynamically (during execution time).
Consider Ruby MRI, for example. The Ruby language supports dynamic types that can be defined during runtime...
...However, this is implemented in C and it's possible to use the code from within C to define new modules and classes. These aren't static types that can be tested during compilation (type creation and identification is performed during runtime).
This is a perfect example showing that C (as a language) can dynamically define "types".
However, this is also a poor example because Ruby's approach is slow. A custom approved can be far faster since it would avoid the huge overhead related to functionality you might not need (such as inheritance).

How to create a DLL, which accepts strings from MT4 and returns back string type?

I am trying for two weeks to create a DLL to which I can pass strings and get back strings. But still no success.
I tried this on Dev-C++(TDM-GCC 4.9.2) and visual studio community 2015. I searched a lot about this and tried almost every sample code I found but I have no success.
I have to use this DLL with MetaTrader Terminal 4.
Here is a one sample code, which I used. This code compiles successfully but when I send a string to this, from MT4, I get an access violation error.
#ifndef MYLIB_HPP
#define MYLIB_HPP
#include <string>
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllimport)
#else
#define MYLIB_API __declspec(dllexport)
#endif
bool MYLIB_API test(const std::string& str);
#endif
bool MYLIB_API MyTest(const std::string& str)
{
return (str == "Hi There");
}
If you do share a C++ string between a DLL and another executable, both need to have been compiled with the same tool-chain. This is because std::string is defined in header only. So, if the DLL and executable use different string headers, they may well be binary incompatible.
If you want to make sure that things do work with different tool-chains, stick to NULL terminated C strings.
You have just experienced one of the MQL4 tricks,the MQL4 string is not a string but a struct thus #import on MQL4 side will make MT4 to inject that, not matching your DLL C-side expectations and the access-violation error is straightforward, as your C-side code tried to access the MQL4 territories...
First rule to design API/DLL: READ the documentation very carefully.
Yes, one may object, that the MQL4 doc is somewhat tricky to follow, but thus more double the Rule#1, read the documentation very, very, very carefully as some important design facts are noted almost hidden in some not very predictable chapters or somewhere in explanations of ENUM tables, compiler directives, pragma-s side-notes et al.
Second rule: design API/DLL interface so as to allow smooth integration
MQL4 has changed the rules somewhere about Build 670+. Good news is, the MetaQuotes has announced, that there will be no further investment on their side into MT4 further developlments, so the MT4-side of the DLL/API integration will hopefully stop from further creeping.
Given your statement, that you design the DLL/API, try to design future-proof specification -- use block of uchar[]-s instead of "interpretations"-sensitive string, pass both inputs and outputs by-reference and return just some form of int aReturnCODE = myDLL_FUNC( byRefParA, byRefParB, byRefRESULT ); and your efforts will result in clean code, better portability among 3rd party language-wrappers and will also minimise your further maintenance costs.
Most likely, your code and the one you're linking against have been compiled with a different ABI for std::string, i.e. the string used by the library has a different memory layout (and sizeof) than the one you're compiling with.
I once ran into this problem when linking against the hdf5 library and using gcc. In this case, the problem could be solved by reverting to a previous ABI, as explained here.
However, the problem also occurred with clang, when such a solution was not available. Thus, to make this all working I had to avoid using std::string in any calls to the library (hdf5 in my case) that was compiled with the different ABI, and instead make do with the hdf5 interface using const char*.

Parsing C++ to make some changes in the code

I would like to write a small tool that takes a C++ program (a single .cpp file), finds the "main" function and adds 2 function calls to it, one in the beginning and one in the end.
How can this be done? Can I use g++'s parsing mechanism (or any other parser)?
If you want to make it solid, use clang's libraries.
As suggested by some commenters, let me put forward my idea as an answer:
So basically, the idea is:
... original .cpp file ...
#include <yourHeader>
namespace {
SpecialClass specialClassInstance;
}
Where SpecialClass is something like:
class SpecialClass {
public:
SpecialClass() {
firstFunction();
}
~SpecialClass() {
secondFunction();
}
}
This way, you don't need to parse the C++ file. Since you are declaring a global, its constructor will run before main starts and its destructor will run after main returns.
The downside is that you don't get to know the relative order of when your global is constructed compared to others. So if you need to guarantee that firstFunction is called
before any other constructor elsewhere in the entire program, you're out of luck.
I've heard the GCC parser is both hard to use and even harder to get at without invoking the whole toolchain. I would try the clang C/C++ parser (libparse), and the tutorials linked in this question.
Adding a function at the beginning of main() and at the end of main() is a bad idea. What if someone calls return in the middle?.
A better idea is to instantiate a class at the beginning of main() and let that class destructor do the call function you want called at the end. This would ensure that that function always get called.
If you have control of your main program, you can hack a script to do this, and that's by far the easiet way. Simply make sure the insertion points are obvious (odd comments, required placement of tokens, you choose) and unique (including outlawing general coding practices if you have to, to ensure the uniqueness you need is real). Then a dumb string hacking tool to read the source, find the unique markers, and insert your desired calls will work fine.
If the souce of the main program comes from others sources, and you don't have control, then to do this well you need a full C++ program transformation engine. You don't want to build this yourself, as just the C++ parser is an enormous effort to get right. Others here have mentioned Clang and GCC as answers.
An alternative is our DMS Software Reengineering Toolkit with its C++ front end. DMS, using its C++ front end, can parse code (for a variety of C++ dialects), builds ASTs, carry out full name/type resolution to determine the meaning/definition/use of all symbols. It provides procedural and source-to-source transformations to enable changes to the AST, and can regenerate compilable source code complete with original comments.

Not naming a type - C++

I am trying to convert an Adobe CS4 based plugin to CS5. This project has never been mine, this is the first time that i am seeing it.
When I compile the source with what i was given, I get errors like: Does not name a type
Example:
SPAPI SPErr SPBasicAcquireSuite( const char *name, int64 version, const void **suite );
I get that:
SPErr does not name a type
I dont see any classes with SPErr being defined, but I doubt that Adobe has left this out of the SDK.
I am using the PS_CS5_SDK_3 SDK
I do not have the possibility to be specific because, of course, I do not have the code. Typically this problem occurs when a type, a class, is not correctly compiled by compiler... meaning that it cannot find it and asks: "what is this?". See macros, or better inspect your code in your hpp files... Probably when porting to CS5 some types have been removed or some...