Loading assemblies from memory (embedded Mono runtime) - c

I want to load mono assemblies from memory. So instead of using the usual mono_domain_assembly_open I use mono_image_open_from_data. The returned image and assembly are OK and the status is MONO_IMAGE_OK.
m_valid = true;
mono_set_dirs(assembliesDir.c_str(), configDir.c_str());
MonoImageOpenStatus status = MONO_IMAGE_ERROR_ERRNO;
m_image = mono_image_open_from_data(data, size, 1, &status);
if(status != MONO_IMAGE_OK || m_image == NULL) {
m_valid = false;
return;
}
m_assembly = mono_assembly_load_from( m_image, assembliesName.c_str(), &status);
if(status != MONO_IMAGE_OK || m_assembly == NULL) {
m_valid = false;
return;
}
However when I try to get a class from the assembly using :
MonoClass *my_class = mono_class_from_name (m_image, name_space.c_str(), name.c_str());
I get my_class == NULL. When I use the usual mono_image_open_from_data Mono returns a valid class instance.
I suspect that the method doesn't load correctly all the references. Do you have any suggestions or workarounds ?

Related

Passing a void (*fn) from a class

I'm writing an auto display turn-off function with ESP32 on Arduino framework with PIO.
I have a Screen class for handling all of the screen functions.
void Screen::turn_off_screen(){
digitalWrite(SCREEN_ENABLE, LOW);
}
void turn_off_screen_wrapper()
{
Serial.println("turn_off_screen_wrapper called");
if (c_screen_Instance != nullptr)
{
c_screen_Instance->turn_off_screen();
}
}
void Screen::auto_display_power_off(int timeout){
Serial.println("auto_display_power_off called");
c_screen_Instance = this;
auto_off_timer = timerBegin(0, 80, true);
Serial.println("auto_off_timer ran");
timerAttachInterrupt(auto_off_timer, &turn_off_screen_wrapper, true);
Serial.println("timerAttachInterrupt ran");
//Converts given seconds from us to seconds
timerAlarmWrite(auto_off_timer,timeout*1000000,false);
timerAlarmEnable(auto_off_timer);
}
The code compiles however I get this when I run it on the board.
auto_display_power_off called
[E][esp32-hal-cpu.c:93] addApbChangeCallback(): duplicate func=400811F8 arg=3FFBDC54
auto_off_timer ran
The screen never gets turned off of course since the callback never runs. Any ideas why this is happening?
is c_screen_Instance global?
is auto_off_timer global?
Consider providing a bit more of your code.
But anyway.
bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
initApbChangeCallback();
apb_change_t * c = (apb_change_t*)malloc(sizeof(apb_change_t));
if(!c){
log_e("Callback Object Malloc Failed");
return false;
}
c->next = NULL;
c->prev = NULL;
c->arg = arg;
c->cb = cb;
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
if(apb_change_callbacks == NULL){
apb_change_callbacks = c;
} else {
apb_change_t * r = apb_change_callbacks;
// look for duplicate callbacks
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
if (r) {
log_e("duplicate func=%8p arg=%8p",c->cb,c->arg);
free(c);
xSemaphoreGive(apb_change_lock);
return false;
}
else {
c->next = apb_change_callbacks;
apb_change_callbacks-> prev = c;
apb_change_callbacks = c;
}
}
xSemaphoreGive(apb_change_lock);
return true;
}
This is addApbChangeCallback's declaration.
Your error comes from this line :
while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
Where r it's a struct to hold all the callbacks.
This error indeed indicates this callback function was already assigned somewhere in your code. r is global, so your code is re-assigning the same callback twice.
Try to either only assign it once, or to unassign the function before assigning it again with removeApbChangeCallback(void * arg, apb_change_cb_t cb) or timerDetachInterrupt
I've also found a reported issue related to timerAttach on the current version here: https://github.com/espressif/arduino-esp32/issues/6730
Try to roll back the Platform PIO's version to a more stable one:
# instead of espressif32
platform = https://github.com/platformio/platform-espressif32.git#<tag-version>
Check on the git link for the available tags you can use.
Problem was that I was attaching the interrupt in the void loop(). Which would run way faster than the actual timer. After moving it to setup (Setup being a placeholder) I plan on having it on a Hardware interrupt it worked as expected.

C - Copying integer

so i am using jansson library and i want to set a value:
json_object_set_new(event, "error_code", json_integer(response->error_code));
The problem is that, i need to free response struct, but still use the value i have set in json_object_set_new.
Should i copy the value from response->error_code and how can i do that?
Some context:
plugin_response: {
if(!response->message && response->error_code == 0) {
response->error_code = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
if(response->error_cause == NULL) {
response->error_cause = g_strdup_printf("%s", "Invalid response");
}
}
json_t *event = json_object();
if(!response->message && response->error_code != 0) {
/* Prepare JSON error event */
json_object_set_new(event, "audiobridge", json_string("event"));
json_object_set_new(event, "error_code", json_integer(response->error_code));
json_object_set_new(event, "error", json_string(response->error_cause));
} else {
event = json_deep_copy(response->message);
}
if(root != NULL)
json_decref(root);
if(jsep != NULL)
json_decref(jsep);
g_free(transaction);
g_free(response);
return janus_plugin_result_new(JANUS_PLUGIN_OK, NULL, event);
}
EDIT: I am also using GLib, so if there is a nifty method for this, i am all ears.
Okey, i read this This article and i understood. I don't need to copy integer i am passing to json_integer(), because it's is not a pointer and is completely isolated from the structs integer.

OpenWrt LibUbi implementation

i'm trying to develop an application (written in ANSI C) for an OpenWrt router using libuci.
I've read this useful post: How to find out if the eth0 mode is static or dhcp?
and i've develop a piece of my application that is able to read network data (in this case i read if ppp is enabled) using uci library.
char path[]="network.ppp.enabled";
struct uci_ptr ptr;
struct uci_context *c = uci_alloc_context();
if(!c) return;
if (strcmp(typeCmd, "GET") == 0){
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if(ptr.flags & UCI_LOOKUP_COMPLETE)
strcpy(buffer, ptr.o->v.string);
uci_free_context(c);
printf("\n\nUCI result data: %s\n\n", buffer);
}
now i want try to SET new network data (so i want enable ppp -> set ppp to 1)
I've write:
}else if (strcmp(typeCmd, "SET") == 0){
if ((uci_lookup_ptr(c, &ptr, path, true) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
ptr.o->v.string = "1";
if ((uci_set(c, &ptr) != UCI_OK) || (ptr.o==NULL || ptr.o->v.string==NULL)) {
uci_free_context(c);
return;
}
if (uci_commit(c, struct uci_package **p, true) != UCI_OK){
uci_free_context(c);
return;
}
}
LibUci documentation is non-existent, there is just some info in the file uci.h, i don't know how fill uci_ptr struct, so i've retrieve it from uci_lookup_ptr , i've change ptr.o->v.string and launch uci_set with new params, but about uci_commit i don't know about struct uci_package **p.
Someone call share with me a bit of documentation or show me some examples?
Thanks a lot
The documentation is very thin on UCI. The way I figured it out is by using the uci_ptr's .value property from the uci structure.
Fromt that, I change the line:
ptr.o->v.string = "1";
to:
ptr.value = "1";
I also changed your commit line as follows:
uci_commit(ctx, &ptr.p, false);
That worked for me.

Problem with the database WPF application it cannot add anything

I was trying to add new row to my database table and it seams that everything is going well in the application WPF and when i close the application the database has not changed(new record was not added in the database ) I tried to use dataadapters so here is my class that i use and the code behing
DD.cs
namespace WpfApplication2
{
class DD
{
private Database1DataSetTableAdapters.Table1TableAdapter _cpuAdapter = null;
protected Database1DataSetTableAdapters.Table1TableAdapter Adapter
{
get
{
if (_cpuAdapter == null)
_cpuAdapter = new Database1DataSetTableAdapters.Table1TableAdapter();
return _cpuAdapter;
}
}
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Insert, true)]
public bool AddCPU(string Naslov, string Avtor, string Lokacija, int Broj, string
Zabeleska, string Izdava)
{
Database1DataSet.Table1DataTable cpus = new Database1DataSet.Table1DataTable();
Database1DataSet.Table1Row cpu = cpus.NewTable1Row();
cpu.Naslov = Naslov;
if (Naslov == null) cpu.SetNaslovNull();
else cpu.Naslov = Naslov;
if (Avtor == null) cpu.SetAvtorNull();
else cpu.Avtor = Avtor;
if (Zabeleska == null) cpu.SetZabeleskaNull();
else cpu.Zabeleska = Zabeleska;
if (Izdava == null) cpu.SetIzdavaNull();
else cpu.Izdava = Izdava;
if (Broj == null) cpu.SetBrojNull();
else cpu.Broj = Broj;
if (Lokacija == null) cpu.SetLokacijaNull();
else cpu.Lokacija = Lokacija;
cpus.AddTable1Row(cpu);
int rowsAffected = Adapter.Update(cpus);
// Return true if precisely one row was inserted, otherwise false
return rowsAffected == 1;
}
HERE IS THE CODE BEHIND
it's an event on button click
string n, a, z,t,l;
int b;
l = txtLokacija.Text;
t = txtBroj.Text;
b = Convert.ToInt32(t);
n = txtNaslov.Text;
a = txtAvtor.Text;
z = txtZabeleska.Text;
t = "NONE";
txtZabeleska.Clear();
DD obj1=new DD();
obj1.AddCPU(n,a,l,b,z,t);
I found IT....when i finished the application and published then it seemed everything ok the database was working properly..i;ve restarted the PC and the newly added record

Should I IUnknown::Release interfaces created with DllGetClassObject

I'm trying to debug some code that uses COM, which I am a beginner at.
The two calls to IUnknown::Release at the end have got me worried.
The interfaces were created with DllGetClassObject and IClassFactory::CreateInstance.
I have seen other similar code that does not call IUnknown::Release on these - which is correct?
int OpenMixer_Win_DirectSound(px_mixer *Px, int index)
{
DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_DATA desc;
HMODULE hDsound = INVALID_HANDLE_VALUE;
GCO DllGetClassObject;
IClassFactory *pcf = NULL;
IKsPropertySet *pps = NULL;
HRESULT hr;
ULONG bytes;
LPGUID guidIn;
LPGUID guidOut;
UINT deviceIn = -1;
UINT deviceOut = -1;
int ret = FALSE;
guidIn = PaWinDS_GetStreamInputGUID(Px->pa_stream);
guidOut = PaWinDS_GetStreamOutputGUID(Px->pa_stream);
do {
hDsound = LoadLibraryA("dsound.dll");
if (hDsound == NULL) {
break;
}
DllGetClassObject = (GCO) GetProcAddress(hDsound, "DllGetClassObject");
if (DllGetClassObject == NULL) {
break;
}
hr = DllGetClassObject(&CLSID_DirectSoundPrivate,
&IID_IClassFactory,
(void **)(&pcf));
if (hr || pcf == NULL) {
break;
}
hr = IClassFactory_CreateInstance(pcf,
NULL,
&IID_IKsPropertySet,
(void **)(&pps));
if (hr || pps == NULL) {
break;
}
/* Do stuff with the interfaces */
} while( FALSE );
if (pps) {
IUnknown_Release(pps);
}
if (pcf) {
IUnknown_Release(pcf);
}
// Free the library. Note that portaudio also opens dsound.dll
// so this probably doesn't do anything until Pa_Terminate is called.
if (hDsound != INVALID_HANDLE_VALUE) {
FreeLibrary(hDsound);
}
}
Absolutely. Both functions create a new interface pointer, they will have a reference count of 1, the AddRef() function was already called. When you're done with it then you have to call Release(). You'll leak memory if you don't. Every interface in COM works this way.
Yes. As seen in DllGetClassObject sample, the return ppvObj will have a refcount.
Yes, DllGetClassObject() will create an object and pass ownership of that object to your code. Your code will now own the object and be responsible for releasing it by calling IUnknown::Release().

Resources