I have a shared library written in C++ that i need to expose for C as well.
Let's say i have to wrap the following class :
class Foo
{
public:
const std::vector<int> &getList() const
{
return m_list;
}
private:
std::vector<int> m_list {0, 1, 2, 3, 4};
};
First wrapper version :
struct wrap_foo
{
Foo m_f;
};
typedef struct wrap_foo *wrap_foo_t;
const int *getList(wrap_foo_t f) // useful ?
{
return f->m_f.getList().data();
}
int listSize(wrap_foo_t f)
{
return f->m_f.getList().size();
}
int getVal(wrap_foo_t f, int i)
{
return f->m_f.getList().at(i);
}
wrap_foo_t createFoo()
{
return new wrap_foo;
}
void cleanFoo(wrap_foo_t f)
{
delete f;
}
2nd wrapper version :
struct vec
{
const int *first;
int size; // number of elements
};
typedef struct vec *vec_t;
vec_t getList2(wrap_foo_t f)
{
vec_t v = new vec;
v->first = f->m_f.getList().data();
v->size = f->m_f.getList().size();
return v;
}
int getVal2(vec_t v, int i)
{
return *(v->first + i);
}
void cleanVec(vec_t v)
{
delete v;
}
For the first version, the C client code would then use the C API in this way :
wrap_foo_t wf = createFoo();
for (int i = 0; i < listSize(wf); i++)
printf("v = %d\n", getVal(wf, i));
cleanFoo(wf);
And in the 2nd version :
wrap_foo_t wf2 = createFoo();
vec_t list = getList2(wf2);
for (int i = 0; i < list->size; i++)
printf("v = %d\n", getVal2(list, i));
cleanVec(list);
cleanFoo(wf2);
The internal list is wrapped into a c structure in the second version, keeping its size. In the first version, each time the class is extended (for example by adding other getList methods, getList1, getList2,..), 2 wrappers functions are needed (one to return a pointer, one to return the size).
Is there a better choice to wrap this class ?
(except from errors that are not handled in this small example here)
Thank you.
Related
I have union as
using my_union = union my_union {
struct {
int var1;
int var2;
};
long
var;
bool operator == (const my_union & oth) {
return var == oth.var;
}
};
using my_union_1d = std::array < my_union, 2 > ;
using my_union_2d = std::array < my_union_1d, 3 > ;
I have some function which accept this array
class test {
public:
void Foo(my_union_2d & arg1);
};
Now I need to check if Mocked-Foo is called with my expected arguments
class TestMock: Public Test {
public: MOCK_METHOD(void, Foo, (my_union_2d & ));
};
my_union_2d expected_args;
EXPECT_CALL( * (TestMock * ) obj, Foo(expected_args)).Times(1):
However code doesn't compile, as the array of array == operator is not found. I tried changing of AllOfArray, but I seem lost in the documentation for GTest. Does anyone know what needs to be done or a Reference point?
Proper operator== that is a member function shall be a const method:
bool operator==(const my_union &oth) const { return var == oth.var;}
After some investigation, I was able to solve the compilation problem.
MATCHER_P(MyMatch, oth, "Arg is not the same")
{
for (uint8_t outer=0; outer <3; outer++)
{
for (uint8_t inner = 0; inner < 2; inner++)
{
if ((arg[inner].var1 != oth[inner].var1) ||
(arg[inner].var2 != oth[inner].var2))
return 0;
}
}
return 1;
}
And Calling as
EXPECT_CALL( * (TestMock * ) obj, Foo(MyMatch(expected_args))).Times(1);
I'm trying to create a libretro core. It will be a standalone game, so I'm setting RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME to true. The documentation suggests that retro_get_memory_* can be used to have data saved without needing to explicitly query RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY:
The save directory should be used to
store SRAM, memory cards, high scores, etc, if the libretro core
cannot use the regular memory interface (retro_get_memory_data()).
How should the core trigger the saving of data using this interface? Or am I misunderstanding the documentation?
I would expect the frontend to call retro_get_memory_{data,size}, read from the exposed buffer when stopping the core, persist the data to disk, and write it back to the exposed buffer the next time the core starts. Instead I observe:
If I don't provide a content file, the frontend never calls retro_get_memory_{data,size}.
If I provide a content file (which is unused), the frontend calls retro_get_memory_{data,size} after retro_load_game but doesn't write to disk.
Note that this question is about save files (automatically persisted data, usually capturing the player's progress), not save states (snapshots of the game state triggered by the user) which are implemented by the *serialize* methods.
Here is a simple example to reproduce the issue (based on this sample):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libretro.h"
static unsigned char c = 0;
void* retro_get_memory_data(unsigned id) {
fprintf(stderr, "retro_get_memory_data(%d)\n", id);
return (id == RETRO_MEMORY_SAVE_RAM) ? &c : NULL;
}
size_t retro_get_memory_size(unsigned id) {
fprintf(stderr, "retro_get_memory_size(%d)\n", id);
return (id == RETRO_MEMORY_SAVE_RAM) ? 1 : 0;
}
#define WIDTH 320
#define HEIGHT 240
static uint32_t* frame_buf;
void retro_init(void) { frame_buf = calloc(WIDTH * HEIGHT, sizeof(uint32_t)); }
void retro_deinit(void) {
free(frame_buf);
frame_buf = NULL;
}
unsigned retro_api_version(void) { return RETRO_API_VERSION; }
void retro_get_system_info(struct retro_system_info* info) {
memset(info, 0, sizeof(*info));
info->library_name = "SaveTest";
info->library_version = "v1";
info->need_fullpath = false;
info->valid_extensions = NULL; // Anything is fine, we don't care.
}
static retro_video_refresh_t video_cb;
static retro_environment_t environ_cb;
static retro_input_poll_t input_poll_cb;
static retro_input_state_t input_state_cb;
void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; }
void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; }
void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; }
void retro_set_environment(retro_environment_t cb) {
environ_cb = cb;
bool no_content = true;
cb(RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME, &no_content);
}
void retro_get_system_av_info(struct retro_system_av_info* info) {
float aspect = (float)WIDTH / HEIGHT;
info->timing = (struct retro_system_timing){
.fps = 60.0,
.sample_rate = 0.0,
};
info->geometry = (struct retro_game_geometry){
.base_width = WIDTH,
.base_height = HEIGHT,
.max_width = WIDTH,
.max_height = HEIGHT,
.aspect_ratio = aspect,
};
}
unsigned retro_get_region(void) { return RETRO_REGION_NTSC; }
bool retro_load_game(const struct retro_game_info* info) {
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) {
fprintf(stderr, "XRGB8888 is not supported.\n");
return false;
}
(void)info;
return true;
}
bool button(unsigned id) {
return input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, id);
}
void retro_run(void) {
input_poll_cb();
if (button(RETRO_DEVICE_ID_JOYPAD_LEFT) && c > 0) --c;
if (button(RETRO_DEVICE_ID_JOYPAD_RIGHT) && c < 255) ++c;
uint32_t color = (255 - c) | (c << 8);
uint32_t* buf = frame_buf;
for (unsigned i = WIDTH * HEIGHT; i > 0; --i) {
*buf = color;
++buf;
}
video_cb(frame_buf, WIDTH, HEIGHT, WIDTH * sizeof(uint32_t));
}
void retro_unload_game(void) {}
size_t retro_serialize_size(void) { return 1; }
bool retro_serialize(void* data, size_t size) {
fprintf(stderr, "serialize(%p, %lu) <= %u\n", data, size, c);
*(char*)data = c;
return true;
}
bool retro_unserialize(const void* data, size_t size) {
c = *(char*)data;
fprintf(stderr, "unserialize(%p, %lu) => %u\n", data, size, c);
return true;
}
void retro_set_controller_port_device(unsigned port, unsigned device) {}
void retro_set_audio_sample(retro_audio_sample_t cb) {}
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) {}
void retro_reset(void) {}
bool retro_load_game_special(unsigned type, const struct retro_game_info* info,
size_t num) {
return false;
}
void retro_cheat_reset(void) {}
void retro_cheat_set(unsigned index, bool enabled, const char* code) {}
It is undocumented but intended that auto save does not trigger for a core without content.
Moreover auto save was not triggering for cores which had content but could support no content. This was unintended and recently fixed.
Reference: https://github.com/libretro/RetroArch/issues/9300
Is there any way, whether union, struct, or something else, to have a group of functions?
typedef struct {
//ERROR
int sqr(int i) {
return i * i;
}
//ERROR
int cube (int i) {
return i * i * i;
}
} test;
Fields in structs can be function pointers:
struct Interface {
int (*eval)(int i);
};
You cannot define the functions in the struct body, but you can assign functions with the same signature to the struct fields:
int my_sqr(int i) {
return i * i;
}
int my_cube(int i) {
return i * i * i;
}
struct Interface squarer = { my_sqr };
struct Interface cuber = { my_cube };
Then call the fields like a normal function:
printf("%d\n", squarer.eval(4)); // "16"
printf("%d\n", cuber.eval(4)); // "64"
Getting errors such as
stats.c:28:36: error: ‘factoryStats’ has no member named ‘candyConsumed’ factoryStatsArray[producer_number].candyConsumed++;
What I want to be able to achieve is to create an array of structs, then access it's members. Is this the wrong way to do it?
Tried using -> but that shouldn't and don't work since I'm storing structs, not pointers to structs.
#include "stats.h"
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int factoryNumber = 0;
int candyProduced = 0;
int candyConsumed = 0;
double minDelay = 0;
double avgDelay = 0;
double maxDelay = 0;
} factoryStats;
factoryStats *factoryStatsArray;
int NUM_FACTORIES = 0;
void stats_init (int num_producers) {
factoryStatsArray = malloc(sizeof(factoryStats) * num_producers);
NUM_FACTORIES = num_producers;
}
void stats_cleanup (void) {
free(factoryStatsArray);
}
void stats_record_produced (int factory_number) {
factoryStatsArray[factory_number].candyProduced++;
}
void stats_record_consumed (int producer_number, double delay_in_ms) {
factoryStatsArray[producer_number].candyConsumed++;
if (factoryStatsArray[producer_number].minDelay == 0) {
factoryStatsArray[producer_number].minDelay = delay_in_ms;
} else {
if (factoryStatsArray[producer_number].minDelay > delay_in_ms) {
factoryStatsArray[producer_number].minDelay = delay_in_ms;
}
}
if (factoryStatsArray[producer_number].maxDelay == 0) {
factoryStatsArray[producer_number].maxDelay = delay_in_ms;
} else {
if (factoryStatsArray[producer_number].maxDelay < delay_in_ms) {
factoryStatsArray[producer_number].maxDelay = delay_in_ms;
}
}
factoryStatsArray[producer_number].avgDelay+= delay_in_ms;
}
void stats_display(void) {
printf("%8s%10s%10s10s10s10s\n", "Factory#", "#Made", "#Eaten", "Min Delay[ms]", "Avg Delay[ms]", "Max Delay[ms]");
for (int i = 0; i < NUM_FACTORIES; i++) {
printf("%8d%8d%8d%10.5f%10.5f%10.5f",
factoryStatsArray[i].factoryNumber, factoryStatsArray[i].candyProduced,
factoryStatsArray[i].candyConsumed, factoryStatsArray[i].minDelay,
factoryStatsArray[i].avgDelay/factoryStatsArray[i].candyConsumed,
factoryStatsArray[i].maxDelay);
}
}
structs cannot be initialized this way. Remove all those = 0 in typedef struct { ... } factoryStats;. Afterwards it compiles as in http://ideone.com/uMgDzE .
So I tried implementing my Quicksort for sorting an array of Edges by their weight which is in int for my Kruskal's algorithm implementation. Is there a built function in javascript for sorting an array of objects by their properties? In this case by their weight. From smallest weight to the largest.
Here is my edge class.
class Edge
{
private int u;
private int v;
private int weight;
public Edge(int i, int i2, int w)
{
u = i;
v = i2;
weight = w;
}
public int getU() {
return u;
}
public int getV() {
return v;
}
public int getWeight() {
return weight;
}
}
Kruskal's code
class MSTKruskal
{
Edge[] mst(int[][] G)
{
Edge A[] = new Edge[G.length - 1];
Forest aForest = new Forest(G.length);
Edge E[] = new Edge[(G.length * G.length - G.length)/2];
int i3 = 0;
for (int i = 0; i < G.length; i++)
{
for(int i2 = i+1; i2 < G.length; i2++)
{
Edge anEdge = new Edge(i, i2, G[i][i2]);
E[i3] = anEdge;
i3++;
}
}
print(E);
//QuickSort(E, 0, E.length);
print(E);
int index = 0;
for (int i = 0; i < E.length; i++)
{
if (aForest.findSet(E[i].getU()) != aForest.findSet(E[i].getV()))
{
A[index] = E[i];
index++;
aForest.union(E[i].getU(), E[i].getV());
}
}
aForest.printA();
return A;
}
In javascript you can pass function as parameter to sort method, this function should take 2 parameters (a and b), and return:
0, if a == b
<0, if a < b
>0, if a > b
In your case it should be something like:
var a=[15,7,100,50];
a.sort(function(a,b){return a.weight-b.weight;});
So you can easily sort by any arrays contents' properties or even more complex criteria.