I want to export a binary Chunk with lua_dump or luaU_dump..
The error: the return is only <-LuaR
Don't have a compile error or static problems with the code, only the <-LuaR return
What can i do? to result the problem?
private:
const char* buildLua(QString luaScript)
{
const Proto* f;
char *byteCode = 0L;
size_t byteCodeLen = 0;
wdata wd = { &byteCodeLen, &byteCode };
string ts = luaScript.toStdString();
const char* cs;
lua_State *L = luaL_newstate();
f=combine(L,0);
luaL_loadstring(L,ts.c_str());
luaL_openlibs(L);
lua_lock(L);
luaU_dump(L,f,kpt_lua_Writer,&wd,1);
lua_unlock(L);
lua_close(L);
cs = byteCode;
return cs;
}
static const char* kpt_lua_Reader(lua_State *L, void *ud, size_t *size)
{
UNUSED(L);
if ((*(int*)ud)--)
{
*size=sizeof(FUNCTION)-1;
return FUNCTION;
}
else
{
*size=0;
return NULL;
}
}
static int kpt_lua_Writer(lua_State * /*l*/, const void *p, size_t sz, void *ud)
{
wdata *wd = (wdata *)ud;
char *newData;
if((newData = (char *)realloc(*(wd->data), (*(wd->len)) + sz))) {
memcpy(newData + (*(wd->len)), p, sz);
*(wd->data) = newData;
*(wd->len) += sz;
} else {
free(newData);
return 1;
}
return 0;
}
static const Proto* combine(lua_State* L, int n)
{
if (n==1)
return toproto(L,-1);
else
{
Proto* f;
int i=n;
if (lua_load(L,kpt_lua_Reader,&i,"=(keppedev)",NULL)!=LUA_OK) fatal(lua_tostring(L,-1));
f=toproto(L,-1);
for (i=0; i<n; i++)
{
f->p[i]=toproto(L,i-n-1);
if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
}
f->sizelineinfo=0;
return f;
}
}
static void fatal(const char* message)
{
QWidget *widget = new QWidget();
QMessageBox::warning(widget,"Keppe Develop",message);
}
http://www.keppe.org/img/LuaR.png
There is no need to use the internals of Lua. In any case, you should call luaL_loadstring or luaL_loadbuffer, not luaL_dostring, which executes the code in the string:
lua_State *L = luaL_newstate();
luaL_loadstring(L,s.c_str());
lua_dump(L,writer,NULL);
lua_close(L);
However, you should test the return values of both luaL_loadstring and lua_dump.
The compiler error is cause by an invalid function prototype where frmDevelop::writer is implemented.
extern "C"
{
static int frmDevelop::writer(lua_State *L, const void *p, size_t size, void *u)
{
// ...
}
}
You only need the static qualifier at the point of declaration in class frmDevelop. Also, extern "C" here isn't right since you're telling the compiler to not mangle the function name. But the compiler cannot honor that request because you're using a C++ feature(writer is part of frmDevelop and so you need the :: scope operator) -- extern "C" just gets ignored for frmDevelop::writer.
Change writer's implementation from:
extern "C"
static int frmDevelop::writer(lua_State *L, const void *p, size_t size, void *u)
{ /* ... */ }
to
int frmDevelop::writer(lua_State *L, const void *p, size_t size, void *u)
{ /* ... */ }
and that'll fix the compile error you're getting.
I am fixing it self with the Code
Source File (Contain)
void frmDevelop::on_actionBuild_Project_triggered()
{
if (!isInLuaMode) return;
const char* output = buildLua(cedit->document()->toPlainText());
int length = strlen(output);
}
Header File (Contain)
private:
const char* buildLua(QString luaScript)
{
string ts = luaScript.toStdString();
lua_State *L = luaL_newstate();
FILE* D = fopen("test.luac","wb");
luaL_openlibs(L);
luaL_loadstring(L,ts.c_str());
lua_lock(L);
int re = lua_dump(L,kpt_lua_Writer,D);
lua_unlock(L);
lua_close(L);
fclose(D);
return QString::number(re).toStdString().c_str();
}
static int kpt_lua_Writer(lua_State * /*l*/, const void *p, size_t sz, void *u)
{
return (fwrite(p,sz,1,(FILE*)u)!=1) && (sz!=0);
}
test.luac must replace with your File Name :D
Related
thanks for your time, so I have a Char* from mqtt
I want to break this down into 3 seperate values
Char* mqttvalue
//Input Would be like the below for example.
mqttvalue = (255,200,230);
// I would like to split the values into the below.
int 1 = 255
int 2 = 200
int 3 = 230
I've tried strtok with no luck. probably something really dumb but some guidance would help.
Thank you
Edit, what I tried.
//Dummy Value for testing
Split("255,240,230");
//Split Value
void Split(char* e) {
String v[3];
char *p;
int i = 0;
p = strtok(e, ",");
while(p && i < 3)
{
v[i] = p;
p = strtok(NULL, ",");
Serial.println(p);
++i;
};
Serial.println(v[0]);
Serial.println(v[1]);
Serial.println(v[2]);
}
Updated the code to the below from a string to char* its all now working.
//Split Value
void Split(char* e) {
char* v[3];
char *p;
int i = 0;
p = strtok(rgb, ",");
while(p && i < 3)
{
v[i] = p;
p = strtok(NULL, ",");
i++;
};
Serial.println(v[0]);
Serial.println(v[1]);
Serial.println(v[2]);
};
As this is quite often asked question and I'd propose more like using wrapper class inheriting Stream interface on C string (and it can be initialized from Arduino String object too).
However usage with Arduino String class is tricky as the original String shouldn't be altered during usage of StringStream, but it's possible to reinitialize it again. Using rvalue (String literal, passed into the class) is forbidden by using non const reference as the parameter of setData method and constructor.
However it's not tested much, so there might be some mistakes. The copy/move constructor and assigment is ommited (and it shouldn't be :D), also using operator=(String&) and operator=(const char*) would be more intuitive interface for it.
class StringStream : public Stream
{
public:
StringStream()
{
setTimeout(1);
}
StringStream(const char * str)
{
setData(str);
}
StringStream(const char * begin, const char * end)
{
setData(begin, end);
}
explicit StringStream(String & view) // cannot be String literal (rvalue) and it gets invalidated if you change original String
{
setData(view);
}
////////////////////////////////////
inline void setData(const char * begin, const char * end)
{
m_start = begin;
m_end = end;
setTimeout(1);
}
inline void setData(const char * begin)
{
setData(begin, begin + strlen(begin));
}
inline void setData(String & view)
{
setData(view.c_str(), m_start + view.length());
}
//////////////////////////////////
// Stream Interface:
virtual int available() override
{
return m_end - m_start;
}
virtual int read() override
{
if (m_start < m_end)
{
return *(m_start++);
}
return -1;
}
virtual int peek() override
{
if (m_start < m_end)
{
return *m_start;
}
return -1;
}
virtual size_t write(uint8_t) override {
return 0;
}
protected:
const char * m_start{0};
const char * m_end{0};
};
And the test program would be like:
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println("Output:");
StringStream test{" 144, 7899, -5478"};
Serial.println(test.parseInt());
Serial.println(test.parseInt());
Serial.println(test.parseInt());
test.setData("1 2");
Serial.println(test.parseInt());
Serial.println(test.parseInt());
delay(2000);
}
I am trying to make a library for redirection of data printed to Print class. I am unfortunately stuck on error that reads
error: cannot declare variable 'diagData' to be of abstract type 'PrintToString'
note: because the following virtual functions are pure within 'PrintToString'
note: virtual size_t PrintToString::write(uint8_t)
I tried several variations of how to implement this but with no luck. (Sourced from the internet)
Links
Print class: github.com/ Print.h and Print.cpp
My code
PrintToString.h
#ifndef PRINT_TO_STRING_H
#define PRINT_TO_STRING_H
#include <Arduino.h>
class PrintToString : public Print
{
private:
String* data;
public:
PrintToString();
~PrintToString();
String* results();
void clear();
size_t write(uint8_t) = 0;
size_t write(const uint8_t* buffer, size_t size);
};
#endif
PrintToString.cpp
#include "PrintToString.h"
PrintToString::PrintToString()
{
data = new String();
}
PrintToString::~PrintToString()
{
delete data;
data = NULL;
}
String* PrintToString::results()
{
return data;
}
void PrintToString::clear()
{
delete data;
data = new String();
}
size_t PrintToString::write(const uint8_t* buffer, size_t size)
{
size_t n = 0;
while (size--)
{
if (data->concat(*buffer++))
n++;
else
break;
}
return n;
}
TestSketch.ino (I have left out content of all the constants)
#include <ESP8266WiFi.h>
#include <PrintToString.h>
const char* WIFI_SSID
const char* WIFI_PASS
const char* API_HOST
const uint16_t API_PORT
const uint16_t LOCAL_UDP_PORT
WiFiUDP UDPClint;
PrintToString diagData;
uint64_t packetNumber = 0;
void setup()
{
WiFi.begin(WIFI_SSID, WIFI_PASS);
UDPClint.begin(LOCAL_UDP_PORT);
while (WiFi.status() != WL_CONNECTED)
delay(500);
WiFi.printDiag(diagData);
sendStringPacket(diagData.result());
diagData.clear();
}
void loop()
{
delay(1000);
}
void sendStringPacket(String payload)
{
UDPClint.beginPacket(API_HOST, API_PORT);
uint64_t thisPNumber = packetNumber++;
String thisPNumberStr;
while (thisPNumber > 0)
{
uint8_t digit = thisPNumber % 10;
thisPNumberStr.concat(digit);
thisPNumber /= 10;
}
UDPClint.write(';');
for (uint64_t i = 0; i < payload.length(); i++)
UDPClint.write(payload.charAt(i));
UDPClint.endPacket();
}
This is because this class has a pure virtual function here:
size_t write(uint8_t) = 0;
A class with a pure virtual function cannot be instantiated. So method write(uint8_t) must be somehow implemented in your code.
EDIT: Consider making use of the code you used in sendStringPacket() for write(uint8_t). You may be able to redirect output without using sendStringPacket(diagData.result()); statement.
I receive this error:
In function 'bool detect_feedback(AudioEffect*)':
54:30: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
55:16: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
55:40: error: cannot convert 'std::shared_ptr<AudioEffect>' to 'AudioEffect*' in assignment
The code is as follows:
#include<stdlib.h>
#include<iostream>
#include<memory>`
//BASE CLASS
// audio and have a subsequent effect (next).
struct AudioEffect
{
virtual ~AudioEffect() = default;
virtual void process(float* buf, size_t num) = 0;
std::shared_ptr<AudioEffect> next;
};
//DERIVING MULTIPLE AUDIO-EFFECTS
//Noise Gate
struct NoiseGate: public AudioEffect
{
float threshold;
void process(float *buf, size_t num)
{
if (*buf > threshold)
*buf = threshold;
}
};
//Gain Boost
struct GainBoost: public AudioEffect
{
float signal;
void process(float *buf, size_t num)
{
*buf = *buf + signal;
}
};
//Compressor
struct Compressor: public AudioEffect
{
float offset;
void process(float *buf, size_t num)
{
*buf = *buf - offset;
}
};
//Function
// Implement a function that checks if there is a feedback loop
// in the effects chain.
//... detect_feedback(...)
//{
//}
bool detect_feedback (AudioEffect *ae)
{
AudioEffect *p, *q;
for (p = ae;p != NULL; p = p->next)
for (q = p->next; q != NULL; q = q->next)
if (typeid(*p) == typeid(*q))
return true;
return false;
}
//MAIN
int main(int argc, char *argv[])
{
return 0;
}
You can not assign a shared_ptr to a raw pointer. You need to use the .get() method to obtain a raw pointer.
(p->next).get()
I have a class that contain some game level settings.
class Stage {
private:
int level;
int stars;
std::string imgName;
public:
int getLevel(){ return level; };
void setLevel(int n){ level = n; };
int getStars(){ return stars; };
void setStars(int n){ stars = n; };
std::string getImgName(){ return imgName; };
void setImgName(std::string name){ imgName = name; };
};
Then in my program I set the info.
Stage* stagesArr = new Stage[3];
stagesArr[0].setLevel(0);
stagesArr[0].setStars(1200);
stagesArr[0].setImgName("stage0.png");
Then if I want to get this info the string is giving me an odd output.
CCLOG("Level: %i", stagesArr[0].getLevel());
CCLOG("Required stars: %i", stagesArr[0].getStars());
CCLOG("Image Name: %s", stagesArr[0].getImgName());
//Level:0
//Required stars: 1200
//Image Name: T%s //Or just random stuff.
What am I missing here?
Suspected that CCLOG() uses the same formatting rules like the <x>printf() function family does, you need to pass a const char* with the format specifier %s.
Your getImgName() returns a std::string value though, which isn't directly compatible with a const char*.
To achieve the latter, you should call the std::string::c_str() function:
CCLOG("Image Name: %s", stagesArr[0].getImgName().c_str());
Also you can improve your getter/setter functions specifying constness applicability more clear:
int getLevel() const { return level; }
// ^^^^^^
int getStars() const { return stars; }
// ^^^^^^
const std::string& getImgName() const { return imgName; }
// ^^^^^ // ^^^^^^
void setImgName(const std::string& name) { imgName = name; }
// ^^^^^
Note:
As a matter of style you can omit the get / set prefixes for getter/setter functions in c++, as the signatures are disambiguate enough:
int Level() const { return level; }
void Level(int n){ level = n; }
int Stars() const { return stars; }
void Stars(int n){ stars = n; }
const std::string& ImgName() const { return imgName; }
void ImgName(const std::string& name){ imgName = name; }
My personally preferred style is to use lower caps and disambiguate class member variables with a _ postfix:
class Stage {
private:
int level_;
int stars_;
std::string img_name_;
public:
int level() const { return level_; }
void level(int n) { level_ = n; }
int stars() const { return stars_; }
void stars(int n){ stars_ = n; }
const std::string& img_name() const { return img_name_; }
void img_name(const std::string& name) { img_name_ = name; };
};
I am trying to return array of structure from the C++ DLL to C# application. I could return structure from DLL Also could able to send list of structure from c# application to C++ DLL and print its data.
But not able to fill and return array of structure from DLL to C# application. Could anybody help on this. Below is the code on which I am currently working:
C# Code:
[StructLayout(LayoutKind.Sequential)]
public struct DATA
{
[MarshalAs(UnmanagedType.I4)]
public int id;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
};
[DllImport("PassStruct.dll")]
private static extern void PrintListOfStructData(IntPtr[] pD, int nSize);
[DllImport("PassStruct.dll")]
private static extern IntPtr ReturnStruct();
public static DATA ReturnStructure()
{
DATA oRData = new DATA();
IntPtr pD = new IntPtr();
pD = ReturnStruct();
oRData = (DATA)Marshal.PtrToStructure(pD, typeof(DATA));
FreeStruct(pD);
return oRData;
}
public static void PrintListOfStructData(List<NativeDLLHelper.DATA> data)
{
int NumberOfElements = data.Count;
DATA oData = new DATA();
IntPtr[] MemPtr = new IntPtr[NumberOfElements];
for (int i = 0; i < NumberOfElements; i++)
{
MemPtr[i] = Marshal.AllocHGlobal(Marshal.SizeOf(oData));
Marshal.StructureToPtr(data[i], MemPtr[i], false);
}
PrintListOfStructData(MemPtr, NumberOfElements);
for (int i = 0; i < NumberOfElements; i++)
{
Marshal.FreeHGlobal(MemPtr[i]);
}
}
C++ DLL Code:
typedef struct _DATA
{
int nID;
wchar_t *sName;
}DATA;
extern "C" DLLEXPORT DATA* ReturnStruct()
{
DATA *obj = new DATA();
obj->nID = 100;
wstring sName = L"String from DLL";
obj->sName = ::SysAllocString(sName.c_str());
return obj;
}
extern "C" DLLEXPORT void PrintListOfStructData(DATA **pD, int nSize)
{
for(int i=0; i<nSize; i++)
{
wcout<<"ID: "<<pD[i]->nID<<endl;
wcout<<"Name: "<<pD[i]->sName<<endl;
}
}
extern "C" DLLEXPORT void FreeStruct(DATA *obj)
{
delete obj;
}
Don't declare PrintListOfStructData as taking an IntPtr array:
[DllImport("PassStruct.dll")]
private static extern void PrintListOfStructData(IntPtr pD, int nSize);
Then, declare all of the structs into the same block of memory:
int size = Marshal.SizeOf(typeof(DATA));
IntPtr MemPtr = Marshal.AllocHGlobal(NumberOfElements * size);
try
{
for (int i = 0; i < NumberOfElements; i++)
{
Marshal.StructureToPtr(data[i], IntPtr.Add(MemPtr, i * size), false);
}
PrintListOfStructData(MemPtr, NumberOfElements);
}
finally
{
if (MemPtr != IntPtr.Zero) Marshal.FreeHGlobal(MemPtr);
}