I'm currently writing a library application for my Teensy using the Arduino IDE and so far, it has been straight forward enough to do. I have however come across a bit of an odd compilation error that I just can't seem to get my head around. My library includes the well known IRRemote Library in order for me to create what is almost a wrapper library in order to be more specific into the way I need to interact with the IR Remote library. The issue I'm having is with one of the IR Remote library functions:
void sendRaw(const unsigned int buf[],unsigned int len, unsigned int);
Although this may seem like a straight forward function to use, the issue i have is with the first argument to the function. I have tried all various ways to pass something to this function paramater but whatever I do, it simply will not compile. Currently i have set a variable
unsigned int bufferToSend[5] = {1,2,3,4,5}; // data is just for example purposes
when i try to call
sendRaw(bufferToSend, 5, 38); // Values are just for example purposes
i get a compiler error of
undefined reference to `IRsend::sendRaw(unsigned int const*, unsigned int, unsigned int)'
Interestingly, if i call the same function directly from inside the Arduino .ino file rather than via my library call, the code compiles and runs perfectly well. Am I missing something blatantly obvious?
With the help of 'Some programmer dude', I was able to resolve this issue. As it was quite rightfully pointed out, I wasn't actually linking against the external library from within my library. having worked with library linking previously, I know this is absolutely fundamental, however with Arduino and its nature, it compiles libraries that are linked against "on-the-go" when you include from the Arduino script and therefore i fell victim to thinking it would be the same in a custom library. I came across a very good write-up of my exact problem below that provides an excellent explanation to some of the Arduino "smoke and mirrors" magic and how to get round the issue I've faced here.
Advanced Arduino – Including Multiple Libraries In Your Project
Related
so I'm starting up a new project and trying to use a PCA9685 chip with an ATMEGA48PB. I use the following library: https://github.com/prestonsn/PCA9685-Multi-Channel-Servo-Controller-Driver-for-AVR-ATmega
and the i2c library that they recommend. So the problem is that the library states pca9685_init() has two variables in it which are both integers, but when I place integers in them, the following error pops up: "undefined reference to `pca9685_init(unsigned char, unsigned int)". Being quite new to this, I have no idea how to fix it. Does anyone have any ideas? (Image linked:(https://i.stack.imgur.com/WBESt.png))
I tried changing the variables to unsigned char and unsigned int, which didn't help, I tried using hexadecimals, integers, unsigned integers, unsigned chars, and so on and even combinations and nothing worked so far. I'm thinking this might be a library integration error or something of the sorts.
EDIT: So I fixed this problem by changing my project into a C executable instead of a C++ executable. I'm curious as to how I would make it work on C++ though, I'd heard that C++ and C are compatible? How come the C library I linked above doesn't work or at least sends weird errors on a C++ executable?
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.
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
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...
I have got a C function in a static library, let's call it A, with the following interface :
int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);
This function will change the value of y an z (this is for sure). I use it from within a dynamic C++ library, using extern "C".
Now, here is what stune me :
y is properly set, z is not changed. What I exactly mean is that if both are initialized with a (pointed) value of 666, the value pointed by y will have changed after the call but not the value pointed by z (still 666).
when called from a C binary, this function works seamlessly (value
pointed by z is modified).
if I create a dummy C library with a function having the same prototype, and I use it from within my dynamic C++ library, it works very well. If I re-use the same variables to call A(..), I get the same result as before, z is not changed.
I think that the above points show that it is not a stupid mistake with the declaration of my variables.
I am clearly stuck, and I can't change the C library. Do you have any clue on what can be the problem ?
I was thinking about a problem on the C/C++ interface, per instance the way a char* is interpreted.
Edit : I finally found out what was the problem. See below my answer.
It looks like a difference between the the way your C library and C++ compiler is dealing with long longs. My guess is that it is that the C library is probably pre C89 standard and actually treating the 64bit long long as a 32bit long. Your C++ library is handling it correctly and placing 64bits on the call stack and hence corrupting y and z. Maybe try calling the function through *int A(unsigned int a, unsigned long b, unsigned int *y, unsigned char z), and see what you get.
Just a thought.
This is one of those questions where there's nothing obviously wrong from what you've described, yet things aren't working the way you expect.
I think you should edit your post to give a lot more information in order to get some sensible answers. In particular, let's start with:-
What platform is this code for:
Windows, linux, something embedded
or ...?
What compiler is the C
static library built with?
What
compiler is the C++ dynamic library
built with?
What compiler is the C
which can successfully call the
library built with?
Do you have a
source-level debugger? If so, can
you step into the C code from the
C++.
Unless you're wrong about A always modifying the data pointed to by Z, the only likely cause of your problem is an incompatibility between the parameter passing conventions . The "long long" issue may be a hint that things are not as they seem.
As a last resort, you could compare the disassembled C++ calling code (which you say fails) and the C calling code (which you say succeeds), or step through the CPU instructions with the debugger (yes, really - you'll learn a good skill as well as solving the problem)
As far as I know, long long is not part of standard C++, maybe that is the source of your problem.
dunno. Try to debug-step into A and see what happens (assembly code alert!)
Maybe you can wrap the original function in a C library that you call from your C++ library?
Based on your points 2 and 3, it seems like this could work.
If it doesn't, it gives you another debug point to find more clues - see which of your libraries the failure first pops up in, and check why 2 and 3 work, but this doesn't - what is the minimal difference?
You could also try to examine the stack that is set up by your function call in each case to check if the difference is here -- considering different calling conventions.
Step 1: Compare the pointers y and z passed from the C++ side with those received by the C function.
P.S. I don't want to sound obvious, but just double-checking here. I suppose when you say that z is modified just fine when called from a C binary, you mean that the data where z is pointing is modified just fine. The pointers y and z themselves are passed by value, so you can't change the pointers.
Another wild guess: are you sure you're linking against the right instance of the function in your C library? Could it be that there are several such functions available in your libraries? In C the linker doesn't care about the return type or the parameter list when deciding how to resolve a function -- only the name is important. So, if you have multiple functions with the same name...
You could programmatically verify the identity of the function. Create a C library that calls your function A with some test parameters and that works fine and that prints the pointer to function A. Link the library into your C++ app. Then print the pointer to the original A function as seen from the C++ code and compare the pointer with that seen by your C library when invoked in the same process.
Again, an obvious one, but who knows... Are you sure the C function you're invoking is stateless, meaning its output depends only on its inputs? If the function isn't stateless, then it might be that the "hidden" state is responsible for the different behavior (not changing the data pointed to by z) of the function when invoked from your C++ app.
First of all, I am very grateful to everyone for your help.
Thanks to the numerous ideas and clues you gave me, I have been able to finally sort out this problem. Your advices helped me to question what I took for granted.
Short answer to my problem : The problem was that my C++ library used an old version of the C library. This old version missed the 4th argument. As a consequence, the 4th argument was obviously never changed.
I am a bit ashamed now that I realised this was the problem. However, I was misslead by the fact that my code was compiling fine. This was due to the fact that the C++ library compiled against the correct version of the C lib, but at runtime it used the old version statically linked with another library that I was using.
C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
|
------> C lib (P) v.1.1
(N) is a dynamic library which is statically linked with (P) version 1.0.
The compiler accepted the call from (M) to the function with 4 arguments because I linked against (P) version 1.1, but at runtime it used the old version of (P).
Feel free to edit this answer or the question or to ask me to do so.
In your C++ program, is the prototype declared with extern "C"?