I have a newb problem with compiling and linking the kissfft library 'out of the box'. I've downloaded the kissfft library and extracted it to a test directory. Upon entering the directory and running 'make testall' I get the following errors, which look like the std c math library is not being linked to properly.
sharkllama#quaaludes:~/KISSFFT/kiss_fft129$ make testall
# The simd and int32_t types may or may not work on your machine
make -C test DATATYPE=simd CFLAGADD="" test
make[1]: Entering directory `/home/sharkllama/KISSFFT/kiss_fft129/test'
cd ../tools && make all
make[2]: Entering directory `/home/sharkllama/KISSFFT/kiss_fft129/tools'
cc -o fft_simd -Wall -O3 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast -Wwrite-strings -I.. -DUSE_SIMD=1 -msse -lm ../kiss_fft.c fftutil.c kiss_fftnd.c kiss_fftr.c kiss_fftndr.c
/tmp/ccFbS0yK.o: In function `kiss_fft_alloc':
kiss_fft.c:(.text+0xd17): undefined reference to `sincos'
kiss_fft.c:(.text+0xd6b): undefined reference to `floor'
kiss_fft.c:(.text+0xe07): undefined reference to `sincos'
kiss_fft.c:(.text+0xeba): undefined reference to `sqrt'
/tmp/ccbYqDcf.o: In function `kiss_fftr_alloc':
kiss_fftr.c:(.text+0x118): undefined reference to `sincos'
kiss_fftr.c:(.text+0x188): undefined reference to `sincos'
collect2: ld returned 1 exit status
make[2]: *** [fft_simd] Error 1
make[2]: Leaving directory `/home/sharkllama/KISSFFT/kiss_fft129/tools'
make[1]: *** [tools] Error 2
make[1]: Leaving directory `/home/sharkllama/KISSFFT/kiss_fft129/test'
make: *** [testall] Error 2
sharkllama#quaaludes:~/KISSFFT/kiss_fft129$
Clearly, the makefile is trying to link to the math library as the -lm option has been included. Can't make any sense of this. I've compiled numerous programs that properly link to the math library before. Any help would be appreciated.
Thanks,
-B
Kissfft is not really something you need to make and install like other libraries. If you need complex ffts, then all you need to do is compile the kiss_fft.c in your project. If you need something more specialized like multidimensional or real ffts, then you should also compile the apropriate file(s) from the tools dir.
The make targets are largely for development testing of kissfft. There are a lot of system requirements to do that testing. Unless you are changing the internals of kissfft, you won't need to use those testing targets.
Just wanted to share a practical example on how to build a simple application using 1D FFT/IFFT from kissfft:
g++ example.cpp -o example -I kissfft kissfft/kiss_fft.c
example.cpp:
#include "kissfft/kiss_fft.h"
int main()
{
// initialize input data for FFT
float input[] = { 11.0f, 3.0f, 4.05f, 9.0f, 10.3f, 8.0f, 4.934f, 5.11f };
int nfft = sizeof(input) / sizeof(float); // nfft = 8
// allocate input/output 1D arrays
kiss_fft_cpx* cin = new kiss_fft_cpx[nfft];
kiss_fft_cpx* cout = new kiss_fft_cpx[nfft];
// initialize data storage
memset(cin, 0, nfft * sizeof(kiss_fft_cpx));
memset(cout, 0, nfft * sizeof(kiss_fft_cpx));
// copy the input array to cin
for (int i = 0; i < nfft; ++i)
{
cin[i].r = input[i];
}
// setup the size and type of FFT: forward
bool is_inverse_fft = false;
kiss_fft_cfg cfg_f = kiss_fft_alloc(nfft, is_inverse_fft, 0, 0); // typedef: struct kiss_fft_state*
// execute transform for 1D
kiss_fft(cfg_f, cin , cout);
// transformed: DC is stored in cout[0].r and cout[0].i
printf("\nForward Transform:\n");
for (int i = 0; i < nfft; ++i)
{
printf("#%d %f %fj\n", i, cout[i].r, cout[i].i);
}
// setup the size and type of FFT: backward
is_inverse_fft = true;
kiss_fft_cfg cfg_i = kiss_fft_alloc(nfft, is_inverse_fft, 0, 0);
// execute the inverse transform for 1D
kiss_fft(cfg_i, cout, cin);
// original input data
printf("\nInverse Transform:\n");
for (int i = 0; i < nfft; ++i)
{
printf("#%d %f\n", i, cin[i].r / nfft); // div by N to scale data back to the original range
}
// release resources
kiss_fft_free(cfg_f);
kiss_fft_free(cfg_i);
delete[] cin;
delete[] cout;
return 0;
}
To use the 2D transforms, include the appropriate header "kissfft/tools/kiss_fftnd.h" and adjust the build command to:
g++ example.cpp -o example -I kissfft kissfft/kiss_fft.c kissfft/tools/kiss_fftnd.c
Simple enough!
Related
I am currently learning C and am trying to understand the possibilities of dynamic libraries.
My current question is, if I have a simple "Hello World" application in C called "ProgA", and this program dynamically loads a shared library with some example code called "LibB", can LibB access a global variable in ProgA, which was declared as external?
Given is the following example code for demonstration of the problem:
file header.h
#ifndef TEST_H
#define TEST_H
typedef struct test_import_s {
int some_field;
} test_import_t;
extern test_import_t newtestimport;
#endif
file prog_a.c
#include <stdio.h>
#include <windows.h>
#include "header.h"
test_import_t newtestimport = {
.some_field = 42
};
int main()
{
HINSTANCE hinstLib;
typedef void (*FunctionPointer)();
newtestimport.some_field = 42;
hinstLib = LoadLibrary("lib_b.dll");
if (hinstLib != NULL)
{
FunctionPointer initialize_lib_b;
initialize_lib_b = (FunctionPointer)GetProcAddress(hinstLib, "initialize_lib_b");
if (initialize_lib_b != NULL)
{
initialize_lib_b();
}
FreeLibrary(hinstLib);
}
return 0;
}
file lib_b.c
#include <stdio.h>
#include "header.h"
test_import_t *timp;
void initialize_lib_b() {
timp = &newtestimport;
int some_field = timp->some_field;
printf("Result from function: %d\n", some_field);
}
file CMakeLists.txt
cmake_minimum_required(VERSION 3.24)
project(dynamic-library-2 C)
set(CMAKE_C_STANDARD 23)
add_library(lib_b SHARED lib_b.c)
set_target_properties(lib_b PROPERTIES PREFIX "" OUTPUT_NAME "lib_b")
add_executable(prog_a prog_a.c)
target_link_libraries(prog_a lib_b)
In the above example, the headerfile header.h defines the struct test_import_t and an external variable newtestimport using this struct. In the C file of the main program prog_a.c one property of this struct is assigned the value 42. It then dynamically loads the library lib_b.c using the Windows API and executes a function in it. The function then should access the variable newtestimport of the main program and print out the value of the variable (42).
This example does not work. The compiler throws the following error:
====================[ Build | prog_a | Debug ]==================================
C:\Users\user1\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\223.8617.54\bin\cmake\win\x64\bin\cmake.exe --build C:\Users\user1\projects\learning-c\cmake-build-debug --target prog_a -j 9
[1/2] Linking C shared library dynamic-library-2\lib_b.dll
FAILED: dynamic-library-2/lib_b.dll dynamic-library-2/liblib_b.dll.a
cmd.exe /C "cd . && C:\Users\user1\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\223.8617.54\bin\mingw\bin\gcc.exe -fPIC -g -Wl,--export-all-symbols -shared -o dynamic-library-2\lib_b.dll -Wl,--out-implib,dynamic-library-2\liblib_b.dll.a -Wl,--major-image-version,0,--minor-image-version,0 dynamic-library-2/CMakeFiles/lib_b.dir/lib_b.c.obj -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
C:\Users\user1\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\223.8617.54\bin\mingw\bin/ld.exe: dynamic-library-2/CMakeFiles/lib_b.dir/lib_b.c.obj:lib_b.c:(.rdata$.refptr.newtestimport[.refptr.newtestimport]+0x0): undefined reference to `newtestimport'
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
How can the example be fixed to accomplish the described goal?
Windows DLLs are self-contained, and can not have undefined references similar to newtestimport, unless these references are satisfied by another DLL.
How can the example be fixed to accomplish the described goal?
The best fix is to pass the address of newtestimport into the function that needs it (initialize_lib_b() here).
If for some reason you can't do that, your next best option is to define the newtestimport as a dllexport variable in another DLL, e.g. lib_c.dll.
Then both the main executable and lib_b.dll would be linked against lib_c.lib, and would both use that variable from lib_c.dll.
P.S. Global variables are a "code smell" and a significant source of bugs. You should avoid them whenever possible, and in your example there doesn't seem to be any good reason to use them.
Suppose I have the following c source code, in dexp_test.c:
#include <stdio.h>
double dexp(double x, double scale, int log);
int main() {
double x;
x = dexp(1 , 2, 0);
printf("Value: %f\n", x);
return 0;
}
where dexp is defined in R's source code (https://github.com/wch/r-source/blob/trunk/src/nmath/dexp.c). I would like to compile this to a standalone executable. I have R 4.0 installed on my system. I have the following gcc lines:
gcc r-source/src/nmath/dexp.c -I/Library/Frameworks/R.framework/Versions/4.0/Resources/include -c -o a.o
gcc dexp_test.c -c -o b.o
These lines run just fine on my system and I am left with new files a.o and b.o without errors.
When I run this line to get an executable:
gcc -o test_exp a.o b.o
...I get these errors:
Undefined symbols for architecture x86_64:
"_R_NaN", referenced from:
_Rf_dexp in a.o
"_R_NegInf", referenced from:
_Rf_dexp in a.o
"_dexp", referenced from:
_main in b.o
(maybe you meant: _Rf_dexp)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I'm definitely missing something conceptually here; how do I get this to compile? If it helps, I'm on OSX 15.6, and the output of gcc -v is
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
You should mention the operating system you are using.
You need to include the appropriate headers. And tell the linker where and which libraries you want to use.
So your source should be
#include <stdio.h>
#include <R.h>
#include <Rmath.h>
int main() {
double x;
x = dexp(1 , 2, 0);
printf("Value: %f\n", x);
return 0;
}
And on the command line you should use the following
gcc -I/Library/Frameworks/R.framework/Versions/4.0/Resources/include -L/Library/Frameworks/R.framework/Versions/4.0/Resources/lib -lR -o test_exp trydexp.c
I have dynamic library created as follows
cat myfile.cc
struct Tcl_Interp;
extern "C" int My_Init(Tcl_Interp *) { return 0; }
1) complile the cc file
g++ -fPIC -c myfile.cc
2) Creating a shared library
g++ -static-libstdc++ -static-libgcc -shared -o libmy.so myfile.o -L/tools/linux64/qt-4.6.0/lib -lQtCore -lQtGui
3) load the library from a TCL proc
then I give command
tclsh
and given command
% load libmy.so
is there any C++ function/ Qt equivalent to load that can load the shared library on demand from another C++ function.
My requirement is to load the dynamic library on run time inside the function and then use the qt functions directly
1) load the qt shared libraries (for lib1.so)
2) call directly the functions without any call for resolve
For example we have dopen, but for that for each function call we have to call dsym. My requirement is only call for shared library then directly call those functions.
You want boilerplate-less delay loading. On Windows, MSVC implements delay loading by emitting a stub that resolves the function through a function pointer. You can do the same. First, let's observe that function pointers and functions are interchangeable if all you do is call them. The syntax for invoking a function or a function pointer is the same:
void foo_impl() {}
void (*foo)() = foo_impl;
int main() {
foo_impl();
foo();
}
The idea is to set the function pointer initially to a thunk that will resolve the real function at runtime:
extern void (*foo)();
void foo_thunk() {
foo = QLibrary::resolve("libmylib", "foo");
if (!foo) abort();
return foo();
}
void (*foo)() = foo_thunk;
int main() {
foo(); // calls foo_thunk to resolve foo and calls foo from libmylib
foo(); // calls foo from libmylib
}
When you first call foo, it will really call foo_thunk, resolve the function address, and call real foo implementation.
To do this, you can split the library into two libraries:
The library implementation. It is unaware of demand-loading.
A demand-load stub.
The executable will link to the demand-load stub library; that is either static or dynamic. The demand-load stub will automatically resolve the symbols at runtime and call into the implementation.
If you're clever, you can design the header for the implementation such that the header itself can be used to generate all the stubs without having to enter their details twice.
Complete Example
Everything follows, it's also available from https://github.com/KubaO/stackoverflown/tree/master/questions/demand-load-39291032
The top-level project consists of:
lib1 - the dynamic library
lib1_demand - the static demand-load thunk for lib1
main - the application that uses lib1_demand
demand-load-39291032.pro
TEMPLATE = subdirs
SUBDIRS = lib1 lib1_demand main
main.depends = lib1_demand
lib1_demand.depends = lib1
We can factor out the cleverness into a separate header. This header allows us to define the library interface so that the thunks can be automatically generated.
The heavy use of preprocessor and a somewhat redundant syntax is needed due to limitations of C. If you wanted to implement this for C++ only, there'd be no need to repeat the argument list.
demand_load.h
// Configuration macros:
// DEMAND_NAME - must be set to a unique identifier of the library
// DEMAND_LOAD - if defined, the functions are declared as function pointers, **or**
// DEMAND_BUILD - if defined, the thunks and function pointers are defined
#if defined(DEMAND_FUN)
#error Multiple inclusion of demand_load.h without undefining DEMAND_FUN first.
#endif
#if !defined(DEMAND_NAME)
#error DEMAND_NAME must be defined
#endif
#if defined(DEMAND_LOAD)
// Interface via a function pointer
#define DEMAND_FUN(ret,name,args,arg_call) \
extern ret (*name)args;
#elif defined(DEMAND_BUILD)
// Implementation of the demand loader stub
#ifndef DEMAND_CAT
#define DEMAND_CAT_(x,y) x##y
#define DEMAND_CAT(x,y) DEMAND_CAT_(x,y)
#endif
void (* DEMAND_CAT(resolve_,DEMAND_NAME)(const char *))();
#if defined(__cplusplus)
#define DEMAND_FUN(ret,name,args,arg_call) \
extern ret (*name)args; \
ret name##_thunk args { \
name = reinterpret_cast<decltype(name)>(DEMAND_CAT(resolve_,DEMAND_NAME)(#name)); \
return name arg_call; \
}\
ret (*name)args = name##_thunk;
#else
#define DEMAND_FUN(ret,name,args,arg_call) \
extern ret (*name)args; \
ret name##_impl args { \
name = (void*)DEMAND_CAT(resolve_,DEMAND_NAME)(#name); \
name arg_call; \
}\
ret (*name)args = name##_impl;
#endif // __cplusplus
#else
// Interface via a function
#define DEMAND_FUN(ret,name,args,arg_call) \
ret name args;
#endif
Then, the dynamic library itself:
lib1/lib1.pro
TEMPLATE = lib
SOURCES = lib1.c
HEADERS = lib1.h
INCLUDEPATH += ..
DEPENDPATH += ..
Instead of declaring the functions directly, we'll use DEMAND_FUN from demand_load.h. If DEMAND_LOAD_LIB1 is defined when the header is included, it will offer a demand-load interface to the library. If DEMAND_BUILD is defined, it'll define the demand-load thunks. If neither is defined, it will offer a normal interface.
We take care to undefine the implementation-specific macros so that the global namespace is not polluted. We can then include multiple libraries the project, each one individually selectable between demand- and non-demand loading.
lib1/lib1.h
#ifndef LIB_H
#define LIB_H
#ifdef __cplusplus
extern "C" {
#endif
#define DEMAND_NAME LIB1
#ifdef DEMAND_LOAD_LIB1
#define DEMAND_LOAD
#endif
#include "demand_load.h"
#undef DEMAND_LOAD
DEMAND_FUN(int, My_Add, (int i, int j), (i,j))
DEMAND_FUN(int, My_Subtract, (int i, int j), (i,j))
#undef DEMAND_FUN
#undef DEMAND_NAME
#ifdef __cplusplus
}
#endif
#endif
The implementation is uncontroversial:
lib1/lib1.c
#include "lib1.h"
int My_Add(int i, int j) {
return i+j;
}
int My_Subtract(int i, int j) {
return i-j;
}
For the user of such a library, demand loading is reduced to defining one macro and using the thunk library lib1_demand instead of the dynamic library lib1.
main/main.pro
if (true) {
# Use demand-loaded lib1
DEFINES += DEMAND_LOAD_LIB1
LIBS += -L../lib1_demand -llib1_demand
} else {
# Use direct-loaded lib1
LIBS += -L../lib1 -llib1
}
QT = core
CONFIG += console c++11
CONFIG -= app_bundle
TARGET = demand-load-39291032
TEMPLATE = app
INCLUDEPATH += ..
DEPENDPATH += ..
SOURCES = main.cpp
main/main.cpp
#include "lib1/lib1.h"
#include <QtCore>
int main() {
auto a = My_Add(1, 2);
Q_ASSERT(a == 3);
auto b = My_Add(3, 4);
Q_ASSERT(b == 7);
auto c = My_Subtract(5, 7);
Q_ASSERT(c == -2);
}
Finally, the implementation of the thunk. Here we have a choice between using dlopen+dlsym or QLibrary. For simplicity, I opted for the latter:
lib1_demand/lib1_demand.pro
QT = core
TEMPLATE = lib
CONFIG += staticlib
INCLUDEPATH += ..
DEPENDPATH += ..
SOURCES = lib1_demand.cpp
HEADERS = ../demand_load.h
lib1_demand/lib1_demand.cpp
#define DEMAND_BUILD
#include "lib1/lib1.h"
#include <QLibrary>
void (* resolve_LIB1(const char * name))() {
auto f = QLibrary::resolve("../lib1/liblib1", name);
return f;
}
Quite apart from the process of loading a library into your C++ code (which Kuber Ober's answer covers just fine) the code that you are loading is wrong; even if you manage to load it, your code will crash! This is because you have a variable of type Tcl_Interp at file scope; that's wrong use of the Tcl library. Instead, the library provides only one way to obtain a handle to an interpreter context, Tcl_CreateInterp() (and a few other functions that are wrappers round it), and that returns a Tcl_Interp* that has already been initialised correctly. (Strictly, it actually returns a handle to what is effectively an internal subclass of Tcl_Interp, so you really can't usefully allocate one yourself.)
The correct usage of the library is this:
Tcl_FindExecutable(NULL); // Or argv[0] if you have it
Tcl_Interp *interp = Tcl_CreateInterp();
// And now, you can use the rest of the API as you see fit
That's for putting a Tcl interpreter inside your code. To do it the other way round, you create an int My_Init(Tcl_Interp*) function as you describe and it is used to tell you where the interpreter is, but then you wouldn't be asking how to load the code, as Tcl has reasonable support for that already.
here is the command line in linux:
icc test.c -o test.o -L/opt/intel/current/mkl/intel64 -I/opt/intel/current/mkl/include -lmkl_intel_ilp64 -lmkl_core -lmkl_scalapack_ilp64
after running this command: I got a long line of undefined reference errors. I have also tried in eclipse but could not resolve the linking problem there too. I would be happy if anyone just help me to run a small code like this:
//test.c- a sample code from user guide
#include "mkl.h"
#define N 5
void main()
{
int n, inca = 1, incb = 1, i;
typedef struct{ double re; double im; } complex16;
complex16 a[N], b[N], c;
void zdotc();
n = N;
for( i = 0; i < n; i++ ){
a[i].re = (double)i; a[i].im = (double)i * 2.0;
b[i].re = (double)(n - i); b[i].im = (double)i * 2.0;
}
zdotc( &c, &n, a, &inca, b, &incb );
printf( "The complex dot product is: ( %6.2f, %6.2f) ", c.re, c.im );
}
my server
> MKLROOT: /opt/intel/current/mkl/
> library: $MKLROOT/lib/intel64/
> include:$MKLROOT/include
ICC 64bit is installed.
thanks in advance.
The best way to get right linkline for Intel MKL is using MKL Linkline Advisor. Even with right LD_LIBRARY_PATH compiler options and set of libraries you link doesn't look right. Should be
-DMKL_ILP64 -I$(MKLROOT)/include -L$(MKLROOT)/lib/intel64 -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -openmp -lpthread -lm
I'm trying to open multiple files simultaneously (random number of files) and store their textstreams in qlist for simple using in other code:
QList<QTextStream> files;
QList<QString> fnames;
fnames.append("file1.txt");
fnames.append("file2.txt");
// ..and so on with random iterations
// collect qtextsrams into qlist
foreach (QString file, fnames) {
QFile f(file);
f.open(QIODevice::ReadOnly);
QTextStream textStream(&f);
files2.append(&textStream);
}
// use qtextstreams in a loop
QList<QTextStream>::iterator i;
for (i = files.begin(); i != files.end(); ++i) {
qDebug() << i->readLine();
}
So i have an error:
/make debug
make -f Makefile.Debug
make[1]: Entering directory `/home/pixx/Workspace/collocs'
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Idebug -o debug/main.o main.cpp
main.cpp: In function ‘int main(int, char**)’:
main.cpp:128: error: no matching function for call to ‘QList<QTextStream>::append(QTextStream*)’
/usr/include/qt4/QtCore/qlist.h:493: note: candidates are: void QList<T>::append(const T&) [with T = QTextStream]
/usr/include/qt4/QtCore/qlist.h:819: note: void QList<T>::append(const QList<T>&) [with T = QTextStream]
main.cpp:117: warning: unused variable ‘cc’
In file included from /usr/include/qt4/QtCore/QList:1,
from main.cpp:1:
/usr/include/qt4/QtCore/qtextstream.h: In member function ‘void QList<T>::node_copy(QList<T>::Node*, QList<T>::Node*, QList<T>::Node*) [with T = QTextStream]’:
/usr/include/qt4/QtCore/qlist.h:695: instantiated from ‘void QList<T>::detach_helper(int) [with T = QTextStream]’
/usr/include/qt4/QtCore/qlist.h:709: instantiated from ‘void QList<T>::detach_helper() [with T = QTextStream]’
/usr/include/qt4/QtCore/qlist.h:126: instantiated from ‘void QList<T>::detach() [with T = QTextStream]’
/usr/include/qt4/QtCore/qlist.h:254: instantiated from ‘QList<T>::iterator QList<T>::begin() [with T = QTextStream]’
main.cpp:133: instantiated from here
/usr/include/qt4/QtCore/qtextstream.h:258: error: ‘QTextStream::QTextStream(const QTextStream&)’ is private
/usr/include/qt4/QtCore/qlist.h:386: error: within this context
/usr/include/qt4/QtCore/qtextstream.h:258: error: ‘QTextStream::QTextStream(const QTextStream&)’ is private
/usr/include/qt4/QtCore/qlist.h:399: error: within this context
make[1]: Leaving directory `/home/pixx/Workspace/collocs'
make[1]: *** [debug/main.o] Error 1
make: *** [debug] Error 2
What should i fix?
I understand that it's very simple question, but i can't find right query for google :(
The first error, namely "no matching function for call to ‘QList::append(QTextStream*)’" is caused by you using & operator in this line:
files2.append(&textStream);
Your list is supposed to be made of QTextStream objects, not pointers to QTextStream objects.
But the real problem lies deeper. To put an object into a list, an object must have copy constructor. QTextStream doesn't have any, since it's not clear how different copies of a same text stream should work together. I suggest you create a list of pointers to text streams, as in "QList ". Of course, in that case don't forget to handle their destruction, when they are no longer needed:
foreach (QTextStream *cur, files) delete cur;
If you need to pass this list between different parts of your code, make multiple copies of it and such, you may need smart pointers (QSharedPointer), but I can hardly think of a task where you'd need to do it to text streams.
I found a solution, thanks Septagram for idea! QList files2; // file list to merge
QList<QTextStream> files;
QList<QString> fnames;
fnames.append("file1.txt");
fnames.append("file2.txt");
// ..and so on with random iterations
QList<QFile *> files2; // file list to merge
QList<QTextStream *> files3;
foreach (QString file, files) {
files2.append(new QFile(file)); // create file obj
files2.last()->open(QIODevice::ReadOnly); // open file
files3.append(new QTextStream(files2.last())); // create textstream
}
QList< QTextStream * >::iterator i3;
for (i3 = files3.begin(); i3 != files3.end(); ++i3) {
qDebug() << (*i3)->readLine();
}