PCA9685 atmel studio library undefined reference - c++

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?

Related

Teensy/Arduino Library compilation errors

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

C++ problems with string

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

movefile() fails error 2 or 123

I'm updating a c++ routine to move files that was written in visual studio express 2008/2010. I'm now running VS Express 2012
Obviously there are changes to the compiler because string functions have to be upgraded to strcpy_s etc. No problem. This is a console app. I never extended my C++ knowledge past C++ to C# etc. as I need little more than to be able to write small utils to do things on the command line. Still I'm able to write somewhat complex utilities.
My issue is movefile() function always fails to move with either error 2 or 123. I'm working in C:\users\alan\downloads folder so I know I have permission. I know the file is there. Small snippet of code is:
char source=".\\test.txt"; // edited for clarity.
char dest=".\\test.txt1";
printf("\nMove\n %s\n to %s\n",source,dest); // just to see what is going on
MoveFile((LPCWSTR) source, (LPCWSTR) dest);
printf("Error %u\n",GetLastError());
output is :
Move
.\test.txt
to .\test.txt1
Error 2
All of my strings are simple char strings and I'm not exactly sure, even after reading, what LPCWSTR was type def'd for and if this is the culprit. So to get this to compile I simply typedef'd my strings. And it compiles. But still it won't move the files.
The code is more complex in developing the source & dest variables but I've reduce it to a simple "just append a 1 to the file name" situation to see if I can just simply rename it. I thought C:\xxx\yyy\zzz\test.txt was maybe wrong in some fashion but that idea fell though with the above test. I've done it with and without the .\ same issue. I'm running out of ideas other than making my own fileopen read/write binary function to replace movefile(). I'm really against that but if I have to I will.
EDIT: I pasted the printf from original code that used FullPathName, I've corrected the snippet.
The fact that you are casting your arguments to LPCWSTR suggests that you are compiling your program with UNICODE defined, which means you are calling MoveFileW and the compiler warned about an argument type mismatch.
Inserting a cast does not fix that. You are telling the compiler to stop complaining, but you haven't actually fixed the problem (the underlying data is still wrong).
Actual solutions:
Use WCHAR as MoveFileW expects (or TCHAR/LPTSTR and the _T macro).
Explicitly call MoveFileA
Compile without UNICODE defined.
Thanks Andrew Medico. I used MoveFileA and the program seems to work now.
I'm not sure I turned off unicode, but I did change one item in the properties.
I'll need to read up on the compiler about unicode/ansi settings. But for now the issue is fixed and I'm sure I've got the idea of what I need to do. "research"!!!!

pwsz string confusion

I have never posted before so I am sorry if I am not clear. I am trying to use a third party DLL written in c++ on 2005 and all I have is some very poor documentation. I am dynamically linking to the DLL and using the Ordinal value read from Dependency walker to get a pointer to a method in the DLL. Such as (LPFNDDLLZC) GetProcAddress(hHILCdll, (LPCSTR)15);
My code is written in C++ compiled in Microsoft VS 6.0, I can not turn on the UNICODE defines or I will break existing code.
The documentation for the DLL says all string arguments are pwsz which I believe means pointer to a wide char string null terminated.
I have tried passing in a pointer to an unsigned short, BSTR and various other things and the DLL crashes on the string. I am totally lost as to why, I believe it has to do with my pwsz string construction and I'm lost as to how to fix this. I have read so may articles related but nothing works.
Can anyone help? I can post code if need be.
Thanks.
You could use MultiByteToWideChar to turn your LPSTR into an LPWSTR which should solve your problem.
Thanks to everyone. I did finally get a copy of the DLL source and my problem wasn't my string construction it was the poor documentation. Turns out they are using double pointers, fixes a ton of things!

Why is my parameter passed by reference not modified within the function?

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"?