So I have this code that's suppose to compute the dot product of a matrix in different ways (one of which is to use blas in a c++), but when I try to use nvcc to compile the code, it doesn't work and it says that I have an undefined reference to ddot. This is weird because I'm pretty sure I'm using the calling notation referenced here for cublas: http://www.sdsc.edu/us/training/assets/docs/NVIDIA-03-Toolkit.pdf
Can anyone help me? Here's a snip of code I'm having trouble with:
#include <cublas.h> //just some included files here. No problems with these
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
extern "C" //This is where I mention the cublas functions are external.
//I think this is necessary since I also have cuda pieces of code
{
double cublasDDOT_(int *n, double *A, int *incA, double *B, int *incB);
void cublasDAXPY_(int *n, double *a, double *A, int *incA, double *B, int *incB);
}
//Stuff happens here
C[i][t]=cublasDDOT_(&n, partA, &incA, partB, &incB); //This is a piece of my function and where the compiler chokes up
This is weird to me. I've also tried removing the "_"'s with no luck.
Here's the compile command I use: nvcc program
Do I need to mention the cublas library during the compile somehow? I have the cuda toolkit installed, but I don't know how to reference the library other than with
#include <cublas.h>
New update
It turns out I get the same output whether I include the cublas.h header or not
I also get the same output whether I type -lcublas or not
Here's the output, which is garbage for all compiles (with/without cublas.h & with/without -lcublas)
nvcc project4.cu -lcublas
/tmp/tmpxft_000051cb_00000000-14_project4.o: In function `ddot(int&, int&, int&, double**&, double**&, double**&, double*&, double*&, int&, int&, double&, double&, double*)':
tmpxft_000051cb_00000000-3_project4.cudafe1.cpp:(.text+0xda1): undefined reference to `cublasDDOT'
/tmp/tmpxft_000051cb_00000000-14_project4.o: In function `daxpy(int&, int&, int&, double**&, double**&, double**&, double**&, double*&, double*&, int&, int&, double&, double&, double*)':
tmpxft_000051cb_00000000-3_project4.cudafe1.cpp:(.text+0xff3): undefined reference to `cublasDAXPY'
collect2: ld returned 1 exit status
Even when compiling with nvcc, you still need to specify the -lcublas link switch.
It looks like you're calling out the function names incorrectly:
cublasDDOT_()
should be:
cublasDdot()
and:
cublasDAXPY_()
should be:
cublasDaxpy()
The naming is case-sensitive.
If you're not sure about the correct naming, refer to the cublas documentation and take a look at the usage in the sample codes
And yes, remove the underscores. I don't understand why you're calling the function names that way. If you mangle a name, there's no way the linker knows what you intend to link it to.
I'm also not sure any of the "extern C" stuff is necessary. That depends on what else is going on in your project, but I don't think you should use "extern C" wrapped around functions that you intend to be linked with the cublas library, if you are compiling/linking with nvcc
Related
I've been inattentive and for some reason created a function that takes two arguments, and I passed it to attachInterrupt like so:
int state = 42;
void simplified_state_handler(){
state++;
}
void interrupt_func(int x, int y) {
simplified_state_handler();
}
attachInterrupt(digitalPinToInterrupt(10), interrupt_func, CHANGE);
The code got compiled with no complaints at all, and it even works. Now, a bit later, I really can't understand why. Reading and digging the attachInterrupt code didn't help. Please explain why can I pass such a function at all. I'm keeping the (now) useless simplified_state_handler in the example, maybe it is important.
The compiler settings of the AVR boards allow it.
It is only a warning: invalid conversion from 'void (*)(int, int)' to 'void (*)()' [-fpermissive].
On other Arduino platforms (SAMD, STM32, esp8266) it is an error.
The compiler settings in AVR platform were benevolent from the start and they can't change them suddenly. Many existing codes would not compile then.
Simply including the OpenCV header results in linking error. Why is that?
// test.cpp
#include <opencv2/opencv.hpp>
int foo();
int bar();
int main() {
}
If I compile the file with g++ test.cpp, the following linking error occurs:
/tmp/ccugmQl4.o: In function `cv::String::~String()':
test.cpp:(.text._ZN2cv6StringD2Ev[_ZN2cv6StringD5Ev]+0x14): undefined reference to `cv::String::deallocate()'
/tmp/ccugmQl4.o: In function `cv::String::operator=(cv::String const&)':
test.cpp:(.text._ZN2cv6StringaSERKS0_[_ZN2cv6StringaSERKS0_]+0x28): undefined reference to `cv::String::deallocate()'
collect2: error: ld returned 1 exit status
If I compile with g++ test.cpp -lopencv_core, it works all right.
My question is:
It seems to me that there's no need to resolve undefined symbols if I do not use it, like the functions foo and bar. There's no definition for them but the compile-link process works alright.
I don't use any OpenCV functions either. Why is there linking error only for OpenCV functions?
And what kinds of stuff defined in headers can cause such a linking error?
If you tweak your example a little bit
// test.cpp
int foo();
int bar() {
foo();
}
int main() {
}
You would notice that it'd stop working because linker won't be able to understand what is foo();
The same thing happens when you include opencv header - there are references to functions which are declared but since you never link opencv itself - linker can't figure what those functions are and where to get them.
I'm writing software to control a bladeRF radio card but I'm running into a strange compiler/linker error that I haven't been able to figure out. My code uses several functions and data structures defined in the library, libbladeRF, but for some reason I can't reference to one specific function.
However, if I modify the call with an improper argument type, g++ will throw an error to let me know that it doesn't conform to the definition, which seems to tell me that the linker is actually able to locate the reference.
What am I missing?
Initial error:
$ g++ bladeRF_test.cpp -o bladeRF_test -lbladeRF
/tmp/ccTWZzdJ.o: In function `enable_xb300()':
bladeRF_test.cpp:(.text+0x36a): undefined reference to `bladerf_xb300_set_amplifier_enable'
Code excerpt:
#include <iostream>
#include <string>
#include <libbladeRF.h>
using namespace std;
...
int set_xb300_pa(bool enable) {
bladerf_xb300_amplifier amp = BLADERF_XB300_AMP_PA;
if ( bladerf_xb300_set_amplifier_enable(dev, amp, enable) ) {
// Print error message
return -1;
} else {
// Print success message
return 0;
}
}
...
Function arguments changed from (dev, amp, enable) to (&dev, amp, enable):
$ g++ blade_hello.cpp -o blade_hello -lbladeRF
blade_hello.cpp: In function ‘int set_xb300_pa()’:
blade_hello.cpp:62:59: error: cannot convert ‘bladerf**’ to ‘bladerf*’ for argument ‘1’ to ‘int bladerf_xb300_set_amplifier_enable(bladerf*, bladerf_xb300_amplifier, bool)
^
In file included from blade_hello.cpp:4:0:
/usr/local/include/libbladeRF.h:2226:15: note: declared here
int CALL_CONV bladerf_xb300_set_amplifier_enable(struct bladerf *dev,
^
I'm trying to simulate a C17 logic circuit in C++ using a Library called LibLCS. Click here to see an example of a digital circuit made with this lib. But isnt working. I cant compile the code and I have no idea why.
#include <lcs/lcs.h>
#include <lcs/nand.h>
#include <lcs/simul.h>
#include <lcs/tester.h>
#include <lcs/changeMonitor.h>
// All libLCS constructs are defined under
// the namespace lcs.
using namespace lcs;
int main()
{
Bus<1> a, b, c, d, e, ga, gb, gc, gd, ge, gf;
Nand<2> nandGate1(ga, (a,b)), nandGate2(gb, (b,d));
Nand<2> nandGate3(gc, (c,gb)), nandGate4(gd, (gb,e));
Nand<2> nandGate5(ge, (ga,gc)), nandGate6(gf, (gc,gd));
ChangeMonitor<5> inputMonitor((a,b,c,d,e), "Input", DUMP_ON);
ChangeMonitor<2> outputMonitor((ge,gf), "Output", DUMP_ON);
Tester<5> tester((a,b,c,d,e));
Simulation::setStopTime(4000); // Set the stop time.
Simulation::start(); // Start the simulation.
return 0;
}
I got the following compilation error:
g++ -o c17 c17.cpp /tmp/cc5TeFfF.o: In function main':
c17.cpp:(.text+0x50a): undefined reference to lcs::Simulation::setStopTime(unsigned int)'
c17.cpp:(.text+0x50f): undefined reference to lcs::Simulation::start()' /tmp/cc5TeFfF.o: In function lcs::Bus<(1)+(1)> const lcs::Bus<1>::operator,<1>(lcs::Bus<1> const&) const':
c17.cpp(.text._ZNK3lcs3BusILi1EEcmILi1EEEKNS0_IXplT_Li1EEEERKNS0_IXT_EEE[_ZNK3lcs3BusILi1EEcmILi1EEEKNS0_IXplT_Li1EEEERKNS0_IXT_EEE]+0x75):
And many more...
From your errors trace that you gave us in comments, I may tell you that you forgot to link your program with your lib.
If your lib is called liblcs.so or liblcs.a, so add this flags to your g++ compilation :
g++ -o c17 c17.cpp -llcs -L"path to the lib folder"
It should works. Or at least it should solve this problem.
Trying to convert a vector of std::string to a vector of const char*:
#include <algorithm>
#include <functional>
#include <string>
#include <vector>
int main(int argc, char** argv)
{
std::vector<std::string> values;
values.push_back("test1");
values.push_back("test2");
values.push_back("test3");
std::vector<const char*> c_values(values.size());
std::transform(values.begin(), values.end(), c_values.begin(), std::mem_fn(&std::string::c_str));
std::transform(values.begin(), values.end(), c_values.begin(), std::bind(&std::string::c_str, std::placeholders::_1));
std::transform(values.begin(), values.end(), c_values.begin(), [](const std::string& str) { return str.c_str(); });
return 0;
}
When compiling with g++ (4.7.2), all three options compile and link fine. When compiling with clang, options 1 and 2 fail to link, producing:
$ clang -std=c++11 -stdlib=libc++ -lc++ stringtransform.cpp
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::c_str() const", referenced from:
_main in stringtransform-ff30c1.o
ld: symbol(s) not found for architecture x86_64
I am finding I need to use the lambda version (option 3) if I want it to link correctly across platforms using both g++ and clang. Am I running into a linker bug or a hole in clang's C++11 support, or is there something wrong with how I'm invoking the mem_fn() and bind() versions?
EDIT:
Error still present on latest Xcode (6.3.2, with clang version 6.1.0:
$ clang -v
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
This seems to be a bug in libc++ versions since LLVM 3.6.0
My guess is they didn't export the std::string::c_str() symbol from their DSO, so the symbol is not global and can't be linked to.
The &string::c_str pointer to member function creates a dependency on the symbol for that function, which can't be resolved by the linker because the definition of the symbol is not global. It sometimes works when optimising because the c_str() function gets inlined, and no external definition for the symbol is needed.
You can workaround it by instantiating the function yourself in your code:
#ifdef _LIBCPP_VERSION
template const char* std::string::c_str() const;
#endif
However you should be aware that your code has a problem. Options 1 and 2 aren't guaranteed to work with any standard library implementation:
std::mem_fn(&std::string::c_str)
std::bind(&std::string::c_str, std::placeholders::_1)
For non-virtual member functions like std::basic_string::c_str() the standard library is free to define additional overloads, or to use different signatures from those specified in the standard. This means any attempt to do &std::a_class::a_nonvirtual_member_function is non-portable, and potentially a bug.
For example, lots of C++98 code that did &std::vector<X>::push_back stopped compiling in C++11 because that is now an overloaded function (there's an overload taking a const lvalue reference and an overload taking an rvalue reference).
This specific example will probably work in practice, because no implementations overload std::basic_string::c_str or give it a funny signature.
The lambda function is fine, because that doesn't take the address of a member function, it just calls it:
[](const std::string& str) { return str.c_str(); }
This way the compiler finds the function using overload resolution, not via a dubious pointer to member function.
I found a workaround: Compiling your code with -Os makes the issue go away.
This seems to be a libc++ problem.
Given this,
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
string s("Hello, World!");
const char * (std::string::*mem_c_str) () const = &std::string::c_str;
cout << (s.*mem_c_str)() << endl;
return 0;
}
We get the same error.
It is fixed by using -stdlib=libstdc++ -lstdc++. It seems to work for any -On flag.