I have two files main.c and foo.c, I am trying to copy an array of functions from one file to another.
My problem is: Only the first item is getting copied.
This is my code:
foo.c:
void foo1();
void foo2();
void foo3();
void foo4();
void foo5();
void foo6();
void foo7();
void (*myFuncs[7])() = {
foo1,
foo2,
foo3,
foo4,
foo5,
foo6,
foo7
};
void* getMyFuncs(){
return myFuncs;
}
main.c:
void (*things[7])();
void main(){
memcpy(things, getMyFuncs(), sizeof(getMyFuncs()));
}
After running, in debug mode, I inspected my array things and only foo1 pointer has copied.
So, my output has:
void (*things[7])() = {
foo1 (hex address here),
0x00,
0x00,
0x00,
0x00,
0x00,
0x00
};
What I expected:
void (*things[7])() = {
foo1 (hex address here),
foo2 (hex address here),
foo3 (hex address here),
foo4 (hex address here),
foo5 (hex address here),
foo6 (hex address here),
foo7 (hex address here)
};
Why only the first item is getting copied?
Thanks
I found the solution, it was a silly mistake!
My line:
memcpy(things, getMyFuncs(), sizeof(getMyFuncs()));
is wrong, I don't want to copy the size of getMyFuncs().
The write way to copy is by getting the size of my array of functions:
memcpy(things, getMyFuncs(), sizeof(things));
Related
my input in systemverilog is in bits; but I need it to be in uint8_t. is API or library can do it? FYI, Im trying to verify verilog results with .C using "dpi".
system verilog:
//import "DPI-C" function int test_encrypt_ecb();
import "DPI-C" function void compute_bit(input bit i_value, output bit result);
import "DPI-C" function bit get_bit(input bit i_value);
import "DPI-C" function void compute_logic_vector(reg[127:0] i_value, reg[127:0] result, int asize);
c:
void compute_reg_vector(const svLogicVecVal* i_value, svLogicVecVal* result,
int asize) {
log_info("dpi_c.compute_reg_vector(): input %s",
svLogicVecVal2String(i_value, asize));
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
int j =0;
struct AES_ctx ctx;
j++;
AES_init_ctx(&ctx, key);
f2(&ctx, i_value);
int i;
for(i=0;i<15;i++){
printf("ECB encrypt: ");
memcpy(&result, i_value, 16);
log_info("dpi_c.compute_reg_vector(): result %s",
svLogicVecVal2String(result, asize));
}
void f2(const struct AES_ctx* ctx, uint8_t* buf)
{
Cipher((state_t*)buf, ctx->Ry);
}
error of c compilation
warning: passing argument 2 of \f2\u2019 from incompatible pointer type [enabled by default]
note: expected \u2018uint8_t *\u2019 but argument is of type \u2018const struct svLogicVecVal *\u2019
void f2(const struct AES_ctx* ctx, uint8_t* buf);
warning: \u2018main\u2019 is normally a non-static function [-Wmain]
int main(void)
There are no API functions to convert from svLogicVecVal to other C types. You have to understand the C data structure representation of a 4-state (0,1,X,Z) data type which is
typedef struct t_vpi_vecval {
uint32_t aval; // 2-state component
uint32_t bval; // 4-state component
} s_vpi_vecval, *p_vpi_vecval;
typedef s_vpi_vecval svLogicVecVal;
A 128-bit packed 4-state value would be stored in an array of 8 32-bit words. The aval/bval words would be interwoven. Assuming you are only dealing with 2-state values, then picking up every other 32-bit word will work for you.
However, if you know your DPI routines only need to deal with 2-state values, then your routines should use bit instead of reg/logic. Then your C routines only need to deal with svBitVecVal, which is defined as
typedef uint32_t svBitVecVal;
Which you can cast to uint8_t* as long as your arguments are multiples of 8 bits.
Note for single bit arguments or return values, it is much more efficient to use C compatible types like byte/int that can be passed by value and require no pointers.
Here is a small example
SystemVerilog code:
module top;
import "DPI-C" function void compute_logic_vector(bit[127:0] i_value);
logic [127:0] x = 128'h69c4_e0d8__6a7b_0430__d8cd_b780__70b4_c550;
initial compute_logic_vector(x); // SV handles the 4- to 2-state conversion for you
endmodule
C code:
#include "svBitVecVal.h" // compiler generated header guarantees prototypes match
#include <stdint.h>
#include <stdio.h>
void compute_logic_vector(const svBitVecVal* i_value) {
uint8_t* buf = (uint8_t*) i_value;
for(int i=0;i<16;i++)
printf("0x%x ",*buf++);
printf("\n");
}
Command line to run Questa:
qrun svBitVecVal.sv -dpiheader svBitVecVal.h svBitVecVal.c
Output:
# 0x50 0xc5 0xb4 0x70 0x80 0xb7 0xcd 0xd8 0x30 0x4 0x7b 0x6a 0xd8 0xe0 0xc4 0x69
I have a simple code of seven segment deceleration :
#include<avr/io.h>
#include<util/delay.h>
int dp=1<<0;
int a=1<<1;
int b=1<<2;
int c=1<<3;
int d=1<<4;
int e=1<<5;
int f=1<<6;
int g=1<<7;
int ss[]={
a|b|c|d|e|f,
b|c,
a|b|g|e|d,
a|b|g|c|d,
f|g|b|c,
a|f|g|c|d,
a|f|g|c|d|e,
a|b|c,
a|b|c|d|e|f|g,
a|b|c|d|f|g,
0x00
};
int main()
{
while(1){}
}
But this gives me error when I am trying to generate .hex from this .c code:
Here is the error:
main.c:12: error: initializer element is not constant
main.c:12: error: (near initialization for 'ss[0]')
...
Same for all element..
Variables with the static storage duration shall be initialized with compile-time constant expressions.
Instead of the set of the variables use an enumeration. For example
#include <stdio.h>
enum
{
dp=1<<0,
a=1<<1,
b=1<<2,
c=1<<3,
d=1<<4,
e=1<<5,
f=1<<6,
g=1<<7
};
int ss[]={
a|b|c|d|e|f,
b|c,
a|b|g|e|d,
a|b|g|c|d,
f|g|b|c,
a|f|g|c|d,
a|f|g|c|d|e,
a|b|c,
a|b|c|d|e|f|g,
a|b|c|d|f|g,
0x00
};
int main(void)
{
return 0;
}
One way to do this is to ensure they are constants (available at compile time), by changing it to:
#define dp 0x01
#define a 0x02
#define b 0x04
#define c 0x08
#define d 0x10
#define e 0x20
#define f 0x40
#define g 0x80
I wouldn't worry too much about making them 1<<n values since the number of times you'll have to change it will be vanishingly small.
Changing them to const int doesn't seem to help. I suspect constexpr would be an ideal solution for this, except for the fact it's C++ :-)
If you have binary constants available to you, you may also want to lokk into something like:
static const int sevenSegMap[] = {
// .abcdefg
0b01111110, // or use 0xfe if no binary constants.
0b00110000,
: and so on
0b01111011,
};
Well, sorry if this is similar to something seen before.
I have the following code:
//kern.cu
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>
extern "C"{
#include "Kernalize.h"
#include <stdio.h>
}
extern "C" {
__device__ void *dat;
__global__ void memManageDevice(void *data){
dat=data;
}
void memManageD(void *data){
printf("A%d",data);
void *d;
printf("B%d",d);
cudaMemcpy(d,&data,sizeof(data),cudaMemcpyHostToDevice);
memManageDevice<<<1,1>>>(data);
}
__global__ void MemManageC(void *r){//don't call this unless in this file.
r=dat;
}
void* memManageH(void *s){
printf("C%d",s);
void *dr;
cudaMalloc((void **)&dr, sizeof(s));
void *hr;
int size=sizeof(s);
MemManageC<<<1,1>>>(dr);
cudaMemcpy(&hr, dr, size, cudaMemcpyDeviceToHost);
printf("D%d",hr);
return hr;
}
__global__ void kernalize(void (*ptr)(void *)) {
(*ptr)(dat);
}
void Start(int d1, int d2, void (*ptr)(void *), void *data) {//TODO: make arrays as to start many kernels
int size=sizeof(data);
// void *ddata;
// bool ab=true;
// bool *coolbeans=&ab;
// memManageD<<<1,1>>>(data);
kernalize<<<d1,d2,d2*size>>>(ptr);
// data=sdata;
// coolbeans=false;
//kernalize(ptr,data);
}
}
And I compile this into a .so:
nvcc --ptxas-options=-v --compiler-options '-fPIC' -o libpar.so --shared kern.cu
Then from normal C I reference it:
typedef void (*gFunc) ();
typedef void (*sFunc) (int,int,gFunc*,void *data);
typedef void* (*hFunc) (void *);
typedef void (*dFunc) (void *);
void toBe(void *data){
data=12;
while(1){}//side-expirement, don't think it's the stem of the issue.
}
int main() {
printf("start");
sFunc fS;
hFunc hS;
dFunc dS;
void* hLibrary = dlopen("./libpar.so", RTLD_NOW | RTLD_GLOBAL);
if(hLibrary == NULL) {
fprintf(stderr, "%s\n", dlerror());
return 1;
}
int i=42;
*(void**)(&dS)=dlsym(hLibrary,"memManageD");
(void) dS(i);
sleep(1);
printf("checkpoint");
*(void**)(&fS)=dlsym(hLibrary,"Start");
(void) fS(2,2,toBe,&i);
sleep(1);
*(void**)(&hS)=dlsym(hLibrary,"memManageH");
int x=(void*) hS(&i);
printf("%d", x);
return 0;
}
As you might be able to tell through my monstrously hideous code, the function toBe is being passed to a CUDA C kernel, where upon execution it's expected to change the non-type variable pointer "data" to 12. "data" is a reference to "i" in the normal c, and starts as 42. Unfortunately, my output is 1, and not 12:
startA42B431891052checkpointC-288453328D1
which is really just garbage memory listings in between a "A42" and a "D1".
I'm relatively new to CUDA C, and to C for that matter. (I spend the majority of my time with higher-level programming languages.)
So the question really is where I am making a stupid mistake, either in my understanding of CUDA, my syntax with C, or my whole perception of how I envisioned this.
Here's my understanding of why the outputs are seen:
A42 is working as expected because i is equal to 42
B431891052 because the pointer void* d is not initialized, and may be containing a garbage value, and the print statement printf("B%d",d) just prints the lower 32 bits of it.
C-288453328 because the statement printf("C%d",s) prints the lower 32 bits of variable i. In 32 bits the number -288453328 corresponds to hexadecimal number 0xEECE8D30; I think it's the lower 32 bits of the stack address 0x7FFFEECE8D30.
D1 because the hr will contain whatever first 8 bytes dr is point to. It is uninitialized, and in this example the value it points to happens to be 1.
I think to assign have D12 the function memManageC may need to be changed to the following:
__global__ void MemManageC(int *r) {
*r = dat;
}
Thus, the content pointed to by r will have the value of dat. Without the de-reference, the function only modifies the argument that's passed in, which is an no-op and may get optimized away by the compiler.
To have D12 also requires toBe to correctly set the value of dat which seems to require some more code changes. toBe is a host-side function, and a usage of a host-side function in __global__ or __kernel__ functions can be found in this answer: Passing Host Function as a function pointer in __global__ OR __device__ function in CUDA
In the following project, the necessary parameters to initialize test.c are arranged in the structure DataStructure (Here I have only a pointer U8* Buffer). During init, the pointer Buffer is initialized (is pointed to an array) and the function test_init passes the initData to test.c. In test.c the content of the array is printed.
main.c
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
void init(DataStructure *pSL);
void main(void);
void main(void) {
DataStructure initData[COUNT];
init(&initData[0]);
test_init(&initData[0]);
test_run();
}
void init(DataStructure *pSL)
{
U8 Buffer[8] = {0xF1 , 0xF2 , 0xF3 , 0xF4 , 0xF5 , 0xF6 , 0xF7 , 0xF8};
DataStructure SL;
U8* pC = &Buffer[0];
SL.Buffer = pC;
*pSL = SL;
}
where test.c and test.h are:
#ifndef TEST_H_
#define TEST_H_
#ifndef U8
typedef unsigned char U8;
#endif
typedef struct{
U8 *Buffer;
} DataStructure;
#define COUNT 1
void test_init (DataStructure *List);
void test_run ();
#endif /* TEST_H_ */
and
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
static DataStructure *pD;
void test_init (DataStructure *_pD)
{
pD = _pD;
printf("\n test_init: ");
for(int i=0;i<8;i++)
printf("0x%0x, ",*(pD->Buffer+i));
}
void test_run (void)
{
printf("\n test_run: ");
for(int i=0;i<8;i++)
printf("0x%0x, ",*(pD->Buffer+i));
}
The output of this code is:
test_init: 0x0, 0x0, 0x0, 0x0, 0xf5, 0xf6, 0xf7, 0xf8,
test_run: 0x0, 0x0, 0x0, 0x0, 0xf5, 0xf6, 0xf7, 0xf8,
which is wrong. But if I print the elements of SL.Buffer within init function as well, i.e if I change the init function as follows:
void init(DataStructure *pSL)
{
U8 Buffer[8] = {0xF1 , 0xF2 , 0xF3 , 0xF4 , 0xF5 , 0xF6 , 0xF7 , 0xF8};
DataStructure SL;
U8* pC = &Buffer[0];
SL.Buffer = pC;
*pSL = SL;
printf("\n main: ");
for(int i=0;i<8;i++)
printf("0x%0x, ",*(SL.Buffer+i));
}
, the array is passed correctly:
main: 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
test_init: 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
test_run: 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
Could anybody explain me whats wrong whit this code and why the problem is fixed just by printing the array in init function?
And is it the right way to initialize and pass a structure containing a pointer?
The code is a simple version of my project. Originaly the DataStructure contains more parameters and the parameter COUNT (size of initData is more than one.
The problem, as I see it is with the usage of Buffer array.
It is local to the init() function, yet you return the address of the first element of the array to be used outside the function, where the array does not exist anymore. Hence, the address is essentially invalid and any attempt to access that memory will cause undefined behavior.
In the second case, it works fine, as you're printing the array before it ceases it's lifetime, so you're getting expected result.
Solution: You need to allocate static storage to the Buffer array, or use memory allocator function so as, the lifetime of the memory supersede the function scope.
I have a C static library and within it I have one function named returnBytes(), this function is defined this way:
extern "C" unsigned char * returnBytes(void)
{
static unsigned char result[50] = { 0xF0, 0xF0, 0xF0 };
return result;
}
on my other project which is using the above static library (.lib) I call the function like this:
unsigned char *output = returnBytes();
but when I print the content of output, its not correct. meaning that calling a custom print function like this does not return the correct values:
print_bytes(output, 50);
On the other hand calling returnBytes() from within the library works fine. Meaning that the values 0xF0, 0xF0, 0xF0 are printed.
Does the static keyword only maintains the variable values within the same project? Could it be that the static keyword doesn't work if used within a static library function that is called from a c lient project?
Should I be using malloc instead and pass a pointer to returnBytes()? is that the only way?
I am running Windows 7, and I using VC12 for compiler for library and client of library.
EDIT: Sorry didn't notice the static. With the static it works.
I just tested your code on osx and it works correctly as below.
test.h:
#ifndef TEST_H
#define TEST_H
#ifdef __cplusplus
extern "C" {
#endif
unsigned char * returnBytes(void);
#ifdef __cplusplus
}
#endif
#endif /* TEST_H */
test.c :
unsigned char * returnBytes(void)
{
static unsigned char result[50] = { 0xF0, 0xF0, 0xF0 };
return result;
}
Built as a library libtest.a and called by main.c in other project
#include <cstdlib>
#include <cstdio>
using namespace std;
#include "./test.h"
int main(int argc, char** argv) {
unsigned char *c = returnBytes();
printf("%x %x %x\n", c[0], c[1], c[2]);
c[1]= 0xd0;
c = returnBytes();
printf("%x %x %x\n", c[0], c[1], c[2]);
return 0;
}
The output is
f0 f0 f0
f0 d0 f0
which means you can both read and write.
static only works inside your function. Moreover any usual variable (located in the stack) will always die at the end of the function, hence the wrong result.
To fix this, use a dynamic allocation inside your function:
unsigned char *result = calloc(50, 1);
result[0] = 0x50;
result[1] = 0x50;
result[2] = 0x50;
return result;