I am going to call gstreamer functions in NPAPI plugin, but what I found is when I invoke method "gst_init" in plugin, it always failed! no matter I call it in a new thread or a child process, it can not get passed. so I'm wonder how can I call the gst_init function in the correct way? :)
for example :
Javascript code: obj.play();
obj is the plugin NPObject.
static void* play(void *) {
GMainLoop *loop;
GstElement *pipeline,*source,*decoder,*sink;
GstBus *bus;
gst_init(NULL, NULL);
...
}
bool plugin_invoke(NPObject *obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result) {
NPUTF8 *name = sBrowserFuncs->utf8fromidentifier(methodName);
if (strcmp(name, plugin_method_name_gs) == 0) {
...
pthread_t tid = 0;
int ret = 10000;
ret = pthread_create(&tid, NULL, play, NULL);
...
return true;
}
sBrowserFuncs->memfree(name);
return false;
}
In fact, this is a linking problem, in Ubuntu 12.04 64bits, we should compile it by using
gcc xxx.c `pkg-config --cflags --libs gstreamer-xxx` -o output_file
(the src file name must followed with command gcc/g++ , some people must met this bug ever.), but I embed this code into a Qt project, I create the makefile by qmake, it can not put the src file name behind gcc/g++ automatic, so when I use ldd to check the share libs, it is not correct.
as I know in Ubuntu 32bits doesn't met this bug.
Related
I have the following code that used to compile and work fine:
std::vector<unsigned char> marshal_as(cli::array<System::Byte>^ const& from)
{
std::vector<unsigned char> result;
result.reserve(from->Length);
for (int i = 0; i < from->Length; i++)
{
result.push_back(from[i]);
}
return result;
}
After updating VisualStudio to version 16.10 - which updates the C++ compiler to version 14.29 - the code produces an error:
error C2664: 'void std::vector<unsigned
char,std::allocator<_Ty>>::push_back(const _Ty &)': cannot convert
argument 1 from 'unsigned char' to 'const _Ty &'
with
[
_Ty=unsigned char
]
message : An object from the gc heap (element of a managed array) cannot be converted to a native reference
message : see
declaration of 'std::vector<unsigned
char,std::allocator<_Ty>>::push_back'
with
[
_Ty=unsigned char
]
Changing the code in the loop body to
unsigned char b = from[i];
result.push_back(b);
fixes the problem.
I would like to understand the cause of this error. Is this somehow related to a change due to the C++ 20 standard?
Is this somehow related to a change due to the C++ 20 standard?
No. While std::vector<>::push() has subtly changed in C++20, it's not a change that materially affects what's going on here, the issue is definitely clr-specific.
I would like to understand the cause of this error.
This is almost certainly (see below) an error that was always present in your code, but was not being reported by previous versions of the C++/CLI compiler.
Consider the following function:
void foo(const int& v) {
int* ptr = &v;
// store ptr somewhere, long-term.
}
It's obvious that invoking foo() with a reference to a gc-backed int would be a recipe for disaster. Yet that's exactly what result.push_back(from[i]); does.
Your code "works" because push_back() happens to do nothing with its parameter that causes an issue. However, the compiler is not supposed to know that.
N.B. I say almost certainly because I'm having a heck of a time tracking down the call signature for cli::array<T>::operator[](std::size_t) const. It's not impossible that it used to return a T and now returns const T%.
I'm starting to get the hang of SWIG, and the latest version(v3.0) of SWIG seems to handle just about everything I need out of the box, including C++11 features, but I have hit a snag when it comes to using shared_ptr with my director classes.
I have been able to get shared_ptr to work with normal proxy classes great, but now on my directors, it seems to not be supported out of the box. It is giving me the auto-generated type like SWIGTYPE_p_std__shared_ptrT_MyDataType_t and is generating a broken interface because it isn't using the same types that the proxy classes use.
I have a simplified example of what I'm trying to do (run with swig -c++ -java Test.i on swig 3.0):
Test.i
%module(directors="1") test
%{
%}
%include <std_shared_ptr.i>
%shared_ptr(MyDataType)
class MyDataType {
public:
int value;
};
class NonDirectorClass {
public:
std::shared_ptr<MyDataType> TestMethod();
};
%feature("director") CallbackBaseClass;
class CallbackBaseClass {
public:
virtual ~CallbackBaseClass() {};
virtual std::shared_ptr<MyDataType> GetDataFromJava() {};
};
Basically what I'm going to be doing is extending the CallbackBaseClass in Java and I want to be able to pass around my shared_ptr wrapped types. The non-director class generates the shared_ptr types just fine. The director class proxy files get generated correctly, but the SwigDirector_ methods in the wrapper reference the incorrect types.
It seems like I could manually repair the files by changing the type of SWIGTYPE_p_std__shared_ptrT_MyDataType_t to MyDataType everywhere, but I'm hoping someone with more swig knowledge can answer the question so this can be generated correctly.
The best clue I have is here, but I'm still trying to figure out how to correctly use these type maps, especially for shared_ptr and not basic primitives.
UPDATE:
The documentation says:
Note: There is currently no support for %shared_ptr and the director feature.
Though it gives no indication as to why. I'd like to know if this is an impossibility with swig directors, if there is a good reason why not to use shared_ptr in directors. It seems like it makes sense to use the same types you use everywhere else. I hope the answer is it is still possible.
The latest version of the SWIG documentation now reads:
"There is somewhat limited support for %shared_ptr and the director feature and the degress of success varies among the different target languages. Please help to improve this support by providing patches with improvements."
To make your example work we seem to need to add four missing typemaps, directorin, directorout, javadirectorin and javadirectorout:
%module(directors="1") test
%include <std_shared_ptr.i>
%{
#include <memory>
#include <iostream>
%}
%shared_ptr(MyDataType)
%feature("director") CallbackBaseClass;
%typemap(javadirectorin) std::shared_ptr<MyDataType> "new $typemap(jstype, MyDataType)($1,true)";
%typemap(directorin,descriptor="L$typemap(jstype, MyDataType);") std::shared_ptr<MyDataType> %{
*($&1_type*)&j$1 = new $1_type($1);
%}
%typemap(javadirectorout) std::shared_ptr<MyDataType> "$typemap(jstype, MyDataType).getCPtr($javacall)";
%typemap(directorout) std::shared_ptr<MyDataType> %{
$&1_type tmp = NULL;
*($&1_type*)&tmp = *($&1_type*)&$input;
if (!tmp) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type");
return NULL;
}
$result = *tmp;
%}
%inline %{
class MyDataType {
public:
int value;
};
class NonDirectorClass {
public:
std::shared_ptr<MyDataType> TestMethod() { return std::make_shared<MyDataType>(); }
};
class CallbackBaseClass {
public:
virtual ~CallbackBaseClass() {};
virtual std::shared_ptr<MyDataType> GetDataFromJava() = 0;
};
void frobinate(CallbackBaseClass& cb) {
std::cout << "In C++: " << cb.GetDataFromJava()->value << "\n";
}
%}
Even though you only ever use the directorout case in your sample the directorin typemap is still required to make the lookup in director_connect succeed, because it depends upon having the correct descriptor.
These four typemaps are equivilent to the in, javain and javaout typemaps in functionality, but reversed because of their role in directors.
They're not complete enough to handle all cases, but they work in your example. The $typemap call inside the descriptor needs a version of SWIG 3 newer than the one included in Ubuntu 14.04 - in the form I wrote it the only version I tested with was checked out from the trunk. You can write the descriptor by hand (which would just be descriptor="LMyDataType;"), but clearly that's less generic. The advantage of writing it as above is that it will handle %rename directives correctly too. This won't handle packages properly though either so you would have to write it manually again in that case too.
I was able to test and run the example, I added the following run.java:
public class run extends CallbackBaseClass {
public MyDataType GetDataFromJava() {
MyDataType val = new MyDataType();
val.setValue(123);
return val;
}
public static void main(String[] argv) {
System.loadLibrary("test");
run r = new run();
System.out.println("In Java: " + r.GetDataFromJava().getValue());
test.frobinate(r);
}
}
And compiled and ran it with:
~/swig-trunk/preinst-swig -Wall -c++ -java test.i
clang++-3.6 -stdlib=libc++ -Wall -Wextra -std=c++1y test_wrap.cxx -o libtest.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux -shared -fPIC
javac run.java
LD_LIBRARY_PATH=. java run
Which when ran gave:
In Java: 123
In C++: 123
I would guess that in the case of Java with shared_ptr+directors the subtleties around getting the descriptor right are probably the main blocker to having this "just work" out the box.
softwarre: ActiveState ActiveTcl 8.5.13.296436/Win7/DEV C++ 5.4.1.
ActiveTcl is installed at D:/TCL/.
error information:
E:\src\c\tcl\main.oIn function `Tcl_AppInit':
8E:\src\c\tcl\main.cundefined reference to `_imp__Tcl_Init'
E:\src\c\tcl\main.oIn function `main':
14E:\src\c\tcl\main.cundefined reference to `_imp__Tcl_Main'
E:\src\c\tcl\collect2.exe[Error] ld returned 1 exit status
26E:\src\c\tcl\Makefile.winrecipe for target 'tcl_test.exe' failed
c source code:
#include <stdio.h>
#include <stdlib.h>
#include <tcl.h>
#include <tk.h>
int Tcl_AppInit(Tcl_Interp *interp)
{
return (Tcl_Init(interp) == (TCL_ERROR))?TCL_ERROR:TCL_OK;
}
int main(int argc, char** argv)
{
printf("--- Tcl Third-Party Shell Start ---\n");
Tcl_Main(argc, argv, Tcl_AppInit);
printf("--- Tcl Third-Party Shell End ---\n");
return 0;
}
In order to access those functions (notably, Tcl_Main) you must link your code against the Tcl DLL (which I think will be tcl85.dll in your installation); it's not a symbol that is exported through Tcl's stub linking mechanism. I don't know exactly how you do that on Windows (nor exactly where it will be located) but instructing your build environment to use the DLL should not be too difficult.
FWIW, Tcl_Init always returns either TCL_OK (i.e., 0) or TCL_ERROR (i.e., 1). You can just return the value directly from your AppInit function if you're not going to install your own commands and functionality after basic initialization.
After playing around a bit I could reproduce and solve this in Visual Studio.
You just have to add D:\Tcl\lib\tcl86.lib to the "Additional Dependencies" under "Linker/Input".
This solved the problem for me.
Edit
You could either pass Tcl_Init to Tcl_Main (If you don't have to do any specific initialization) or just return the result of Tcl_Init like this:
int Tcl_AppInit(Tcl_Interp *interp)
{
return Tcl_Init(interp);
}
After being told in this question that my preferred solution was impossible, I'm now trying to implement a workaround. Instead of declaring my interface that inherits from IClosable in C++/CX, I'm declaring it in raw IDL. But that doesn't seem to work either.
I've created an IDL file FooSpace.idl containing
import "inspectable.idl";
import "Windows.Foundation.idl";
namespace FooSpace
{
[uuid(01234567-89AB-CDEF-FEDC-BA9876543210)]
[version(42)]
interface Foo : IInspectable requires Windows.Foundation.IClosable
{
}
}
and generate Windows Runtime metadata from it with
midlrt /nomidl /metadata_dir "C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral" FooSpace.idl
The generated FooSpace.winmd looks alright when I disassemble it with ildasm -- in particular, Foo appears to inherit from IClosable in just the same way IInputStream does in the system-provided Windows.winmd.
However, when I try to use it from C++/CX -- not even implement it, just pretending for the time being that someone else has implemented it with WRL or whatever -- it doesn't seem to work. Here's my test C++/CX source file:
void works(Windows::Storage::Streams::IInputStream^ istream) {
Platform::IDisposable^ local = istream ;
}
void doesnt(FooSpace::Foo^ foo) {
Platform::IDisposable^ local = foo ;
}
which produces an error for Foo but not for IInputStream:
C:\cygwin\tmp>cl /nologo /c /ZW /FU FooSpace.winmd testit.cpp
testit.cpp
testit.cpp(5) : error C2440: 'initializing' : cannot convert from 'FooSpace::Foo ^' to 'Platform::IDisposable ^'
No user-defined-conversion operator available, or
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
What am I doing wrong here?
On the other hand the equivalent C# code seems to compile fine:
public class Whatever {
public static void Works(Windows.Storage.Streams.IInputStream istream) {
System.IDisposable local = istream ;
}
public static void AlsoWorks(FooSpace.Foo foo) {
System.IDisposable local = foo ;
}
}
If you add a call to mdmerge to your cmds it should work:
midlrt /nomidl /metadata_dir "C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral" FooSpace.idl
mdmerge -metadata_dir "C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral" -i "." -o "merged" -v -partial
cl /nologo /c /ZW /FU merged\FooSpace.winmd /EHsc testit.cpp
With the 'merged' winmd file I am able to compile code like:
namespace ClosableTest
{
ref class Test sealed
: FooSpace::Foo
{
public:
virtual ~Test()
{
FooSpace::Foo^ f = nullptr;
Platform::IDisposable^ d = f;
}
};
}
The original FooSpace.winmd file that is generated by midlrt references Windows.Foundation (C:\Windows\system32\WinMetadata\Windows.Foundation.winmd) while the mdmerge output references Windows (C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral\Windows.winmd).
It is interesting that you were able to reference the mildrt-output winmd file in a c# project without problems because in the blog post How to reference C++ WRL Components from a .NET project Kevin Stumpf describes that he had some problem when not using mdmerge first.
I have embeded a simple NPAPI plugin in a Google chrome extension.It gets installed on Google Chrome (it is shown in about:plugins) but the background html page shows "missing plugin" and when a method is called (say plugin.foo), it shows a message saying "the plugin does not have the method foo"
My invoke call looks something like this
static bool
invoke(NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result) {
logmsg("invoke");
int error = 1;
char *name = npnfuncs->utf8fromidentifier(methodName);
if(name) {
if(!strcmp(name, "foo")) {
...
....
return invokeDefault(obj, args, argCount, result);
}
}
// aim exception handling
npnfuncs->setexception(obj, "exception during invocation");
return false;
}
https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins
according to this documentation, i have modified my NP_GetValue function and the plugin does not have NPP_SetWindow since i didnt want it to be a windowed plugin.
Am I going wrong somewhere?
Also point out any other places that may have a scope of error.
Thank you
Regards
"Missing plugin" can show either if the plugin isn't loaded (e.g., you typo'd the MIME type in the object tag), or if the plugin crashes during initialization.
Have you tried running with --plugin-startup-dialog to see if your plugin is actually instantiated, and if so debug it?