Failed to compile Boilerplate Generated Based on GstPlugin - gstreamer

I have followed the instruction available in Gst Plugin Development Basics in constructing the boilerplate for my sample plugin which is HelloWorld in this case.
I have created the sample plugin by calling the make_element tool in the cloned repo
../tools/make_element HelloWorld
After that, I have modified the meson.build in gst-plugin directory to include the generated source files namely gsthelloworld.h and gsthelloworld.c
helloworld_sources = [
'src/gsthelloworld.c'
]
gsthelloworld = library('gsthelloworld',
helloworld_sources,
c_args: plugin_c_args,
dependencies : [gst_dep],
install : true,
install_dir : plugins_install_dir,
)
I encountered errors after doing meson build && ninja -C build:
gst-template/build/../gst-plugin/src/gsthelloworld.c:184: undefined reference to `GST_HELLOWORLD'
**there are multiple lines of the same errors happen at different part of the source file.
I cant seem to find the declaration of GST_HELLOWORLD in either generated source files.
Looking at the tutorial in Gst Plugin Development Basics, I see there was a declaration of macro that follows the similar naming convention with mine being HelloWorld while the provided sample being MyFilter.
#define GST_MY_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter))
However, I see none of the macro in the generated source files. So, I guess it might have been written somewhere else as the template provided in form of gstplugin.c and gstplugin.h looks very similar to the generated source files and can be compiled successfully if I remove my sample plugin from the build file.
Thus, is there any step I miss that is relevant for the compilation?
Thanks.
EDITED:
I was doing this on a PC with Ubuntu 18.04(gstreamer 1.14.5)

In
#define GST_TYPE_HELLOWORLD (gst_my_filter_get_type())
G_DECLARE_FINAL_TYPE (GstHelloWorld, gst_hello_world,
GST, PLUGIN_TEMPLATE, GstElement)
replace PLUGIN_TEMPLATE with HELLOWORLD

I compared with a working plugin and this modification to gsthelloworld.h worked for me :
#define GST_TYPE_HELLOWORLD (gst_my_filter_get_type())
G_DECLARE_FINAL_TYPE (GstHelloWorld, gst_hello_world,
GST, PLUGIN_TEMPLATE, GstElement)
// You need to add this one below in your gsthelloworld.h
#define GST_HELLOWORLD(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_HELLOWORLD,GstHelloWorld))

The gstmyfilter.h which worked for me is:
#ifndef __GST_MYFILTER_H__
#define __GST_MYFILTER_H__
#include <gst/gst.h>
G_BEGIN_DECLS
/* #defines don't like whitespacey bits */
#define GST_TYPE_MYFILTER \
(gst_my_filter_get_type())
#define GST_MYFILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MYFILTER,GstMyFilter))
#define GST_MYFILTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MYFILTER,GstMyFilterClass))
#define GST_IS_MYFILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MYFILTER))
#define GST_IS_MYFILTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MYFILTER))
typedef struct _GstMyFilter GstMyFilter;
typedef struct _GstMyFilterClass GstMyFilterClass;
struct _GstMyFilter
{
GstElement element;
GstPad *sinkpad, *srcpad;
gboolean silent;
};
struct _GstMyFilterClass
{
GstElementClass parent_class;
};
GType gst_my_filter_get_type (void);
G_END_DECLS
#endif /* __GST_MYFILTER_H__ */
Also these are build commands:
meson --reconfigure build
ninja -C build

Related

C++ Preprocessor doesn't process define as expected

I'm having problems with cpp Preprocessor. I have this Input.h file like this:
#ifndef PLATFORM_MOBILE1111
#define MyTest WEB111
#endif
int MyTest;
I process it with this command (on OSX):
cpp -E -P Source/Input.h Generated/Output.h
I get this:
#define MyTest WEB111
int MyTest;
i.e. macro MyTest is not getting applied. Why?
After a bunch of experimentation, I found that if I insert an empty line, variable definition, a comment or any other line after #ifndef line - then it works fine.
#ifndef PLATFORM_MOBILE1111
#define MyTest WEB111
#endif
int MyTest;
So the input above gets processed correctly into:
int WEB111;
Can someone explain to me why that is happening? and how to solve that? Is there an option that I can pass?
Edit: I also found that ## (concatenation operator) doesn't work too!
Strange! You clearly found a bug in the clang preprocessor!
I can reproduce this as well (Apple LLVM version 8.1.0 (clang-802.0.42)) on OSX.
This also starts working as expected when you remove the spaces before #define (indentation), but leading spaces should not matter at all, and a lot of editors indent #defines inside #ifdefs.
One hint on what is going on is that in the bogus versions the #define is still present in the processed source code, while in the correct version it is not. So apparently the preprocessor did not recognize the #define as such at all.
Even this fails (note the leading space):
#define MyTest WEB111
int MyTest;
While this works as expected:
#define MyTest WEB111
int MyTest;
And this results in WEB222:
#define MyTest WEB111
#define MyTest WEB222
int MyTest;
While this results in WEB111:
#define MyTest WEB111
#define MyTest WEB222
int MyTest;
Crazy!1!! :-)
It seems that always the first indented #define gets ignored.
Now the 'solution': Use:
gcc -E Source/Input.cpp -P -o Generated/Output.cpp
This works as expected, although it is using the same LLVM.
So I assume the gcc executable initializes the preprocessor differently than the cpp. This is still a bug in cpp.
I found out that running preprocessor through c++ rather than cpp solves both of my problems:
c++ -E -P Source/Input.h Generated/Output.h
BTW.: you need to add -x c++ flag if you file is not using regular c/c++ extention for c++ command. cpp works fine without that.

build R package with C code (without Rcpp)

environment:
OS:Windows10 [10.0.14393]
R:3.4.1 (2017-06-30) -- "Single Candle" 32-bit
Rstudio:1.0.143
Rtools:3.4.0.1964
This is my first time to build R package (named testt).
I'm trying to build a package with some C code without using Rcpp.
I have put all .c files (called lca.c, rlca_cond.c, rlca_prev.cand rlca_condprev.c)
and their header file in /src.
And I have some C function defined in chanmat.c, declared in chanmat.h.
chanmat.c and chanmat.h are also in /src.
Both lca.h, rlca_cond.h, rlca_prev.h and rlca_condprev.h have #include 'chanmat.h'.
In chanmat.h, I use the following to prevent multiple definition when compiling.
#ifndef CHANMATH_H
#define CHANMATH_H
...
#endif
I have also used following in NAMESPACE file (generated by roxygen2)
useDynLib(testt,lca)
useDynLib(testt,rlca_cond)
useDynLib(testt,rlca_prev)
useDynLib(testt,rlca_condprev)
useDynLib(testt,chanmat)
When I run build & reload, I got following error
Updating testt documentation
Loading testt
Error in FUN(X[[i]], ...) :
no such symbol chanmat in package
C:/Users/elephant/Desktop/project/testt/src/testt.dll
Calls: suppressPackageStartupMessages ... assignNativeRoutines ->
getNativeSymbolInfo -> lapply -> FUN
��������
Exited with status 1.
I have no idea why chanmat.c/chanmat.h are failed to compile.
This question bothers me for a long time.
Any thoughts on how to fix this?

Dynamically use QGLWidget or QOpenGLWidget depending on Qt version

My code is supposed to compile and run on platforms before and after Qt 5.4 where QOpenGLWidget was introduced, superseding QGLWidget. I thought I could write code like this to support both:
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
# define USE_Q_OPEN_GL_WIDGET
#endif
#ifdef USE_Q_OPEN_GL_WIDGET
# include <QOpenGLWidget>
#else
# include <QGLWidget>
#endif
class GLWidget :
#ifdef USE_Q_OPEN_GL_WIDGET
public QOpenGLWidget
#else
public QGLWidget
#endif
{
Q_OBJECT
public:
[...]
But that will not fly because moc does not seem to understand the preprocessor directives and will generate code for the wrong class.
I tried to work around the problem by adding a add_custom_command directive to my CMakeLists.txt which would run ${CMAKE_CXX_COMPILER}" -E -P -x c++-header ... on the file before passing it to moc. But that doesn't seem to work either as the preprocessor will remove the magic Q_OBJECT line, indicating that indeed moc must be run before the C preprocessor is run.
What other options do I have?
Must I resort to having two nearly identical header files (except for two lines) and then choose the right one at build time in cmake?
EDIT
To test this problem, try out the following:
on a Ubuntu trusty system which comes with qt 5.2.1 (you can create a chroot using sudo debootstrap trusty ubuntu-trusty) do:
apt-get install libqt5opengl5-dev build-essential qttools5-dev qt5-default
then create glwidget.h containing:
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QtGlobal>
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
# define USE_Q_OPEN_GL_WIDGET
#endif
#ifdef USE_Q_OPEN_GL_WIDGET
# include <QOpenGLWidget>
#else
# include <QGLWidget>
#endif
class GLWidget :
#ifdef USE_Q_OPEN_GL_WIDGET
public QOpenGLWidget
#else
public QGLWidget
#endif
{
Q_OBJECT
};
#endif
then run:
$ moc -v
moc 5.2.1
$ moc glwidget.h | grep QGL || echo "not found"
not found
$ moc glwidget.h | grep QOpenGL >/dev/null && echo "found!"
found!
so you see that even though qt 5.2.1 does not have QOpenGL, moc interpretes the preprocessor directive that way
we can change the version check to the much simpler
#if QT_VERSION >= 0x050400
if we try again with that check, then moc in qt 5.2.1 in Ubuntu trusty generates the right results
so we think that we found the solution and try running moc from a more recent qt distribution on the same code. This time I'm using moc from qt 5.5.1 in Debian unstable and I get:
$ moc -v
moc 5.5.1
$ moc glwidget.h | grep QOpen || echo "not found"
not found
$ moc foo.h | grep QGL > /dev/null && echo "found"
found
most funnily, if under qt 5.5.1 I turn the version check macro mack to using
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
then it does work!
So in summary, moc does understand some preprocessor directives but the ones it does understand are different between versions before and after qt 5.4. There does not seem to exist a common preprocessor directive that is understood by both. Thus I do not see a way to solve this problem using preprocessor directives.
You can use CMake to generate this header. Put this code into it:
#include <#GL_CLASS#>
class GLWidget : #GL_CLASS#
{
Q_OBJECT
public:
[...]
And then do this in CMakeLists.txt:
set(GL_CLASS <depending on Qt version>)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) #this is because configure_file produces its output in the build dir
configure_file(yourheader.h output.h #ONLY)
Finally, use #include "output.h" in your code.

Chain of C libraries into C++

I have a very trivial problem including a chain of C libraries into a C++ main project. I've experience with C but it's the first time that I'm programming in C++.
The structure of the project is a single folder with inside:
main.cpp
Mylib_1.c
Mylib_1.h
Mylib_2.c
Mylib_2.h
main calls -> Mylib_1.h that calls -> My_lib2.h
//main.cpp
#include "Mylib_1.h"
//Mylib_1.h
#include "Mylib_2.h"
main contains both Mylib_1 and Mylib_2 functions and typedef structs
Mylib_1 uses typedef structs and functions of Mylib_2
Everything inside each Mylib_x.h is wrapped between extern "C", like this:
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
#ifdef __cplusplus
extern "C" {
#endif
mycode
#ifdef __cplusplus
}
#endif
#endif
But when I try to compile it with eclipse kepler on Ubuntu 12.04 x64, I get:
Mylib_1.h error: Mylib_2_type_t does not name a type
main.cpp error: Mylib_2_function1 was not declared in this scope
...
Only the above sections are marked as error in eclipse, the header looks included fine.
Furthermore according to eclipse, the __cplusplus flag is false into Mylib_2.h but true into Mylib_1.h
Thinking of some eclipse error, I've tried to manually build the project via g++ (v4.6.3) but I got the same exact problem when I've tried to link the libraries .o with the main.cpp
Seems stupid but I can't figure out what could it be. Any suggestion?
Thank you
Have you checked that your lines
#ifndef __MYLIB_X_H
#define __MYLIB_X_H
are really different for the two files,
e.g. _MYLIB1_H and _MYLIB2_H?

Creating shared and static libraries using g++ (under Windows)

How do I create static and dynamic libraries for Windows using g++?
I've found a few commands for Linux for creating .so files and I've tried to apply them on a Windows shell, but they build .dll files that my applications fail to link with at runtime.
I've only managed to build .dll files using Visual C++ but I would like to build them manually on the command line, preferably using g++. I would also like to know how to build static libraries too for Windows.
You need to prefix with the attribute :
__declspec(dllexport)...
all the features you want to expose.
See this.
Example for a C function:
__declspec(dllexport) int __cdecl Add(int a, int b)
{
return (a + b);
}
This can be simplified using MACROS: everything is explained on this helpful page.
For C++ classes, you only need to prefix each class (not every single method)
I usually do it that way :
Note : The following also ensures portability...
Include File :
// my_macros.h
//
// Stuffs required under Windoz to export classes properly
// from the shared library...
// USAGE :
// - Add "-DBUILD_LIB" to the compiler options
//
#ifdef __WIN32__
#ifdef BUILD_LIB
#define LIB_CLASS __declspec(dllexport)
#else
#define LIB_CLASS __declspec(dllimport)
#endif
#else
#define LIB_CLASS // Linux & other Unices : leave it blank !
#endif
Usage :
#include "my_macros.h"
class LIB_CLASS MyClass {
}
Then, to build, simply :
Pass the option -DBUILD_LIB to the usual compiler command line
Pass the option -shared to the usual linker command line