I implement a wrapper around the Google V8 engine. I wrote a class:
class Es
{
public:
Es();
~Es();
int Init(const char* exec_path);
int CreateContext(uint& id);
int RemoveContext(const uint id);
protected:
Global<Context> global_context;
std::map<uint, Persistent<Context>*> contexts;
Isolate* isolate = nullptr;
private:
uint next_id = 1;
};
I want to create Contexts, hold them in the contexts var, and remove them oneday. So, I init the V8 engine:
int Es::Init(const char* exec_path)
{
v8::V8::InitializeICUDefaultLocation(exec_path);
v8::V8::InitializeExternalStartupData(exec_path);
std::unique_ptr<Platform> platform = platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
V8::Initialize();
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
isolate = Isolate::New(create_params);
if (!isolate)
return InitError;
return Success;
}
And after that I want to create a context, using int Es::CreateContext(uint& id). Its called after Init.
int EasyProspect::CreateContext(uint& id)
{
if (!isolate)
return NotInitializedError;
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Context> local_context = Context::New(isolate);
Persistent<Context> context(isolate, local_context);
contexts.emplace(id, &context);
return Success;
}
But I can't do that, the code crashes on Context::New(isolate). Why? isolate is not null, I enter the local scope...
Your best bet is to compile in Debug mode and run in a debugger. Then it should be easy to tell what's causing the crash.
(At the very least, you should post a complete reproducible example, including specifying the V8 version you're working with, how that's built/configured, and how you're compiling your code.)
If I had to guess: the Platform and the ArrayBuffer::Allocator need to stay alive for as long as you want to use the V8 instance, but in your code they are both destroyed at the end of Es::Init. Since Es is a wrapper class, you can easily add fields there to keep them around.
Related
working on implementing an Serial receive library for a specific hardware sending information to a ESP8266 device, I came across the following issue
for some background:
I use sloeber the eclipse IDE for arduino programming, with Arduino IDE the same issue exists
__cplusplus gives me 201103, so I assume I am on c++11
explanation of the setup:
I have derived classes which represents interpreted packages received from serial
these classes are all derived form on base class which implements some common methods, here methodA (in reality: length of
data, and getter for the data)
to forward these packets around I have created a class which has a member of a struct (sData) which has a tagged union inside. for simplicity I only use sData here not the class containing it.
the union uUnion is the one holding the packets content in form of derived packages, only one at a time, but able to contain every derived class available.
i do not use any dynamic object creation (no new), to prevent memory leaks
maybe there are better solution to this problem. Ideas are appreciated. But I would like to focus on why my implementation is not working
problem
the usage of the members-functions of the derived classes out of the union.
I can call them directly without problem.
But I am not able to create a pointer out of the union to the derived class instance and call that member.
//this is the base class
class cBaseA{
public:
virtual void methodA(void){
Serial.print(" A ");
Serial.println(i);
}
int i; //some attribute to work with
private:
};
//first derived class
class cDerivedA: public cBaseA{
public:
void methodA(void) {
Serial.print(" DerivedA ");
Serial.print(i);
Serial.print(" ");
Serial.println(ii);
}
int ii; //additional attribute
private:
};
//second derived class
class cDerivedB: public cBaseA{
public:
void methodA(void) {
Serial.print(" DerivedB ");
Serial.print(i);
Serial.print(" ");
Serial.println(ii);
}
int ii;
private:
};
//third derived class
class cDerivedC: public cBaseA{
public:
void methodA(void) {
Serial.print(" DerivedC");
Serial.print(i);
Serial.print(" ");
Serial.println(ii);
}
int ii;
private:
};
//this is the structure to pass different derived instances around
struct sData{
enum eDataType{
eunkown,
eDerivedA,
eDerivedB,
eDerivedC
} DataType;
union uUnion{
cDerivedA DerivedA;
cDerivedB DerivedB;
cDerivedC DerivedC;
~uUnion(){};
uUnion(){};
} ;
uUnion DataUnion;
sData(void){DataType=eDataType::eunkown;};
sData(const sData &Data){
this->DataType=Data.DataType;
switch(this->DataType){
case eDataType::eDerivedA:
this->DataUnion.DerivedA=Data.DataUnion.DerivedA;break;
case eDataType::eDerivedB:
this->DataUnion.DerivedB=Data.DataUnion.DerivedB;break;
case eDataType::eDerivedC:
this->DataUnion.DerivedC=Data.DataUnion.DerivedC;break;
case eDataType::eunkown:
break;
}
}
~sData(){};
};
void DataFunction(struct sData *Data){
Serial.println("A1:");
Data->DataUnion.DerivedB.methodA(); //works fine
cDerivedB *DerivedB;
DerivedB=&(Data->DataUnion.DerivedB); //this works
DerivedB->methodA(); //compiles, but execution exception, code 28
}
void setup(){
Serial.begin(9600);
delay(2000);
sData Data;
cDerivedB DerivedB1;
DerivedB1.i=1;
DerivedB1.ii=2;
Data.DataType=sData::eDataType::eDerivedB;
Data.DataUnion.DerivedB=DerivedB1;
DataFunction(&Data);
}
what I tried so far:
the absence of the virtual destructor of cBaseA has no influence (I tried already with it)
to make the union anonymous did not changed anything
to make a reference to the unions content results in the same error:
cDerivedB &DerivedB;
DerivedB=&(Data->DataUnion.DerivedB);
DerivedB.methodA();
I am able to make copy to out of the union to the base class, but this causes slicing, and the call ends in the base class, not as I need in the derived class
the question is: why does this exception happen, if the direct call is possible?
What is the right way to get a handle (pointer, reference) of the unions content and call the member? I know that there are discussions out there, that unions should only contain simple data types. Is this just a flaw of the compiler (c+11) letting me write this?
But still, direct access is possible. Why not via pointer?
many thanks in advance if somebody is able to put that cloud away I can not see through.
How to achieve gtest or gmock for the private and protected member function. I am new to gtest and gmock. Below is the code for which i need to do gtest or gmock along with my attemp.
constexpr static char _session[]{"S_ID"};
typedef struct {
int session;
} Session;
typedef std::function<void(const Session &)> SessionCallback_t;
class Service : public ParentService {
public:
Service();
void registerCallback(const SessionCallback_t & callback);
protected:
virtual void notifyHandler(const Json::Value & data) override;
virtual void notifyState();
private:
Session mSession;
SessionCallback_t mCallback;
void jsonParse(const Json::Value & json_data);
};
My Attemp which doesn't compile
class TestService : public Service {
public:
TestService(): Service() {
}
bool registerCallback(const SessionCallback_t & cb) {
// how to achive this?
}
};
class MyTestService : public ::testing::Test {
protected:
virtual void SetUp() {
}
virtual void TearDown() {
}
};
TEST_F(MyTestService , registerCallbackTest) {
TestService service;
EXPECT_TRUE(service.registerCallback(SessionCallback_t));
}
I am stuck with the below interface
1.registerCallback()
2.notifyHandler()
3.notifyState()
4.jsonParse()
Please though some light to proceed further.
Welcome to Stack Overflow!
First, let me recommend this recent episode of CppCast on Designing for Testing. The podcast notes that if you find your code is hard to test, it means it is too tightly coupled and is thus poorly designed.
It also (rightly, IMHO) recommends that you test only public functions. If you find yourself needing to test the private functions, you should probably refactor the code.
One way to do that is to break your code into multiple classes with the public functions you want to test. Then, your composite class can either create and own the class directly (appropriate if it's a basic type with no dependencies or complex resources of its own such as a vector or string class) or can use dependency injection to pass in the dependencies as constructor or method parameters (appropriate for databases, network connections, file systems, etc.).
Then in testing, you pass in a test double, such as a mocked object or a simplified implementation like an in-memory database instead of an out-of-process database connection, that acts like the object but does what you need in the test situation.
That's the basic advice. In your specific case, it looks like you're trying to override a non-virtual function in your TestService. What are you wanting to test exactly?
I wouldn't expect EXPECT_TRUE(service.registerCallback(SessionCallback_t)); to compile because SessionCallback_t names a type, not an instance of a type, so you can't pass it in. Again, what are you trying to accomplish?
Update to comment:
Mocking requires virtual functions (or duck typing) and dependency injection.
If you just want to test registerCallback(), I suspect you don't need a mock at all. Rather, you need to look at the function's documentation to see what it says it will do -- sometimes called the contract. For instance, what are the preconditions and postconditions of the function? What are the error cases it might encounter? These are what a unit test should cover.
For instance, does it retain only one callback (hint: as written, yes)? What happens when you call it when there is already a callback registered? Does it tolerate default-initialized std::function objects being passed in?
The bigger question is, how do you validate that your test is correct. If you start triggering notifications on your callback, you're venturing beyond the scope of testing this function in isolation. Instead, you could create an accessor class in your test to publicize what is private so you can validate. Still, you can't compare std::function for equality, so the best you can do is to invoke it and check that an expected side effect happens:
class TestService : public Service {
public:
const SessionCallback_t& getCallback() const { return mCallback; }
};
struct TestCallback
{
int mCount = 0;
void operator()( const Session& ) { ++mCount; }
};
Then in your test, you can write a tests like:
TEST_F(MyTestService , Test_registerCallback_BadCallback) {
auto service = TestService{};
EXPECT_THROW( service.registerCallback( SessionCallback_t{} ), std::out_of_range );
}
// Register and check that it's our callback
TEST_F(MyTestService , Test_registerCallback_CallbackSaved) {
auto service = TestService{};
auto callback = TestCallback{};
EXPECT_TRUE( service.registerCallback( callback ) );
EXPECT_EQ( callback.mCount, 0 );
auto actualCallback = service.getCallback();
EXPECT_TRUE( actualCallback );
actualCallback();
EXPECT_EQ( callback.mCount, 1 );
}
TEST_F(MyTestService , Test_registerCallback_CallbackOverwrite) {
auto service = TestService{};
auto callback1 = TestCallback{};
auto callback2 = TestCallback{};
EXPECT_TRUE( service.registerCallback( callback1 ) );
EXPECT_TRUE( service.registerCallback( callback2 ) );
EXPECT_EQ( callback1.mCount, 0 );
EXPECT_EQ( callback2.mCount, 0 );
auto actualCallback = service.getCallback();
EXPECT_TRUE( actualCallback );
actualCallback();
EXPECT_EQ( callback1.mCount, 0 );
EXPECT_EQ( callback2.mCount, 1 );
}
I'm trying to compile ncurses 5.9 for an embedded system (using buildroot) and I get this error message:
In file included from ../c++/cursesm.h:39:0,
from ../c++/cursesm.cc:35:
../c++/cursesp.h: In member function ‘T* NCursesUserPanel<T>::UserData() const’:
../c++/cursesp.h:256:43: error: no matching function for call to
‘NCursesUserPanel<T>::get_user() const’
return reinterpret_cast<T*>(get_user ());
Here's the code in question:
/* We use templates to provide a typesafe mechanism to associate
* user data with a panel. A NCursesUserPanel<T> is a panel
* associated with some user data of type T.
*/
template<class T> class NCursesUserPanel : public NCursesPanel
{
public:
NCursesUserPanel (int nlines,
int ncols,
int begin_y = 0,
int begin_x = 0,
const T* p_UserData = STATIC_CAST(T*)(0))
: NCursesPanel (nlines, ncols, begin_y, begin_x)
{
if (p)
set_user (const_cast<void *>(p_UserData));
};
// This creates an user panel of the requested size with associated
// user data pointed to by p_UserData.
NCursesUserPanel(const T* p_UserData = STATIC_CAST(T*)(0)) : NCursesPanel()
{
if (p)
set_user(const_cast<void *>(p_UserData));
};
// This creates an user panel associated with the ::stdscr and user data
// pointed to by p_UserData.
virtual ~NCursesUserPanel() {};
T* UserData (void) const
{
return reinterpret_cast<T*>(get_user ());
};
// Retrieve the user data associated with the panel.
virtual void setUserData (const T* p_UserData)
{
if (p)
set_user (const_cast<void *>(p_UserData));
}
// Associate the user panel with the user data pointed to by p_UserData.
};
Line 256 is this one: return reinterpret_cast<T*>(get_user ());
The problem here was due to a compiler update to g++ (Debian 7.2.0-5). New compilers have better error handling, and this old code was written without its benefit. The solution here is to either use a more recent version of ncurses (no-go for my particular situation) or use an older compiler. Since my host system is Debian, I used update-alternatives to switch to g++ 6.4 and the problematic error message went away.
I'm leaving this here because Google gave me no good results for the error message.
I am working on a COM-style complier cross-compatible plugin framework relying on compatible virtual table implementations for ABI compatibility.
I define interfaces containing only pure virtual member functions and an overridden delete operator to channel destruction to the place of implementation.
This works well with extern "C" factory functions instantiating the plugin implementation of the interface and returning an interface-type pointer.
However, I was wondering if smart pointers wouldn't be a more modern way to manage the lifetime of the plugin object. I think I have actually managed to
create a standard-layout shared_ptr/weak_ptr that uses a reference count object defined and implemented the same way as the plugin interfaces.
It looks something like this:
class IRefCount
{
public:
virtual void incRef() = 0;
virtual void decRef() = 0;
virtual bool incRefIfNZ() = 0;
virtual void incWRef() = 0;
virtual void decWRef() = 0;
virtual long uses() const = 0;
protected:
~ref_count_base() = default; //prohibit automatic storage
}
template <typename Ty>
class shared_ptr
{
private:
Ty* ptr_;
IRefCount* ref_count_;
public:
//member functions as defined by C++11 spec
}
Three questions:
Before the smart pointer the factory function looked like this:
extern "C" IPlugin* factory() { try { return new Plugin(); } catch (...) { return nullptr; } }
Now, it looks like this:
extern "C" shared_ptr<IPlugin> factory() { try { return shared_ptr<IPlugin>(new Plugin()); } catch (...) { return nullptr; } }
VS2013 is giving me warning C4190: 'factory' has C-linkage specified, but returns UDT 'shared_ptr' which is incompatible with C. According to MSDN this is OK, provided that both caller and callee are C++.
Are there any other potential issues with returning standard-layout objects from "C" linkage functions?
Calling conventions. Should I be specifying __stdcall for all pure-virtual interface functions and factory functions?
I am using <atomic> for the reference count. I am writing platform-independent code and I have not yet tried compiling for ARM. According to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dht0008a/ch01s02s01.html armcc does not implement std::atomic. Any better compilers/stl out there?
Just stumbled upon strange behavior.
I have an unmanaged class (actually wrapper around some native lib):
//.h
class Wrapper
{
private:
void(*pCallback)(int, int /*, int*/);
public:
void SetCallback(void(*callback)(int, int /*, int*/));
void InvokeCallback();
};
//.cpp
void Wrapper::SetCallback(void(*callback)(int, int /*, int*/))
{
pCallback = callback;
}
void Wrapper::InvokeCallback()
{
pCallback(0, 0 /*, 0*/); //(1)
//(3)
}
And managed class which is winforms control and uses unmanaged wrapper described above:
public ref class MineControl : public System::Windows::Forms::Control
{
private:
Wrapper *pWrapper;
delegate void CallbackDelegate(int, int /*, int*/);
public:
MineControl()
{
/* rest of initialization here */
pWrapper = new Wrapper;
auto dlg = gcnew CallbackDelegate(this, &MineControl::Method);
auto ptr = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(dlg);
void(*callback)(int, int /*, int*/) = (void(*)(int, int /*, int*/))(ptr.ToPointer());
pWrapper->SetCallback(callback);
pWrapper->InvokeCallback();
}
void Method(int a, int b /*, int c*/)
{
//some code or even nothing at all
//(2)
}
}
This works fine.
Until I uncomment third parameter. After that I put breakpoint on (1). I can enter to MineControl::Mehod - (2). But everything fails on exiting this method. Point (3) become unreachable. I'm getting unhandled exception on exiting that method. Moreover being attached, VS still cannot handle that exception (all settings to debug unmanaged and managed code are set - this is the only case VS cannot catch exception). So Windows tries to handle it - standard App has stopped working window with two options - Debug and Close program. But I cannot debug because VS is still attached and either do not want to detach or app dies on VS detach.
I can wrap all parameters into some structure and this will work well. However can someone explain me why adding third parameter makes it impossible to get back from managed to unmanaged code?
I have no idea what is going on.
Environment: VS2013, x86 project, .net4.5
Ok, I'll post answer by myself. Solution is actually in Hans's comment.
Default calling convention is sdtcall but in my case I need cdecl calling convention.
Decorating delegate with [UnmanagedFunctionPointer(CallingConvention.Cdecl)] attribute solved my problem.
There is also а valuable note that keep delegate in a local variable is a bad idea.