Creating a simple server-client program using rpcgen.
I'm writing this .x file:
program REMOTE_PROG {
version MSG_RCV {
int STRLEN(string) = 1;
double SQUARE(double *) = 2;
int NUM_OF_DEV(int *) = 3;
} = 1;
} = 99;
executing with rpcgen file.x -> generates file_svc.c.
in the file_svc.c file, for some reason, it generates each function case with _svc extension:
case STRLEN:
xdr_argument = xdr_wrapstring;
xdr_result = xdr_int;
local = (char *(*)()) strlen_1_svc; //<--_SVC
break;
and when I try to compile the server after implementing the functions
int * strlen_1(char **, CLIENT *);
the compiler raises that error:
"_strlen_1_svc", referenced from:
_remote_prog_1 in file_svc-8501b7.o
ld: symbol(s) not found for architecture x86_64
But if I'll delete that auto generated _svc extension,local = (char *(*)()) strlen_1; //no _svc the program will compile successfully.
Why does this happen? why does the rpcgen adds the _svc extension to the functions and am I doing something wrong when I delete the _svc?
P.S same error also for square and num_of_dev functions, gave only strlen for example.
Thanks!
That's the convention, the _svc is short for service.
Your server needs to implement the service function, that is the strlen_1_svc function.
Your client calls the strlen_1 function. rpcgen + the RPC library does all the inbetween - it generates code for strlen_1 used by the client which will serialize the data and transfer it to the server, where an event loop dispatches the call to your code in the strlen_1_svc function.
After execution of rpcgen ex7.x you should have created the client and server stubs ex7_clnt.c and ex7_svc.c and also a header file ex7.h
In the header file you will have declared both functions strlen_1 and strlen_1_svc, they have to have different names as they are different functions: first one is on the client side and invokes the second one on the server side through RPC call.
Related
I am using FFF - Fake Function Framework to stub out some calls in my unit tests. This is working fine in many instances. I can stub out any of the functions I have written myself, as well as any calls to FreeRTOS functions. When I call these functions from within a test, it is the Fake that is called. However, I cannot get it to work with the STM32 HAL functions - these function calls always call the real function.
I am defining fakes in the test source file, as follows:
FAKE_VALUE_FUNC(BaseType_t, xTaskCreate, TaskFunction_t, const char *, configSTACK_DEPTH_TYPE, void *, UBaseType_t, TaskHandle_t *);
FAKE_VALUE_FUNC(HAL_StatusTypeDef, HAL_TIM_Base_Init, TIM_HandleTypeDef*);
Then the first test, which works just fine, is as follows:
TEST(HeaterTestGroup, WHEN_BothTaskCreationsFail_THEN_HeaterInitFails)
{
ADC_HandleTypeDef TestADC;
BaseType_t taskCreateOutcomes[2] = { pdFAIL, pdFAIL };
SET_RETURN_SEQ(xTaskCreate, taskCreateOutcomes, 2);
CHECK_EQUAL(Heater_init(&TestADC), ERROR);
}
The function under test, HeaterInit() calls two functions:
InitialiseHeater1Task(hadc);
InitialiseHeater2Task(hadc);
Each of which contains a similar call to create a FreeRTOS task:
taskCreationSuccess = xTaskCreate( ControlTask, // Function that implements the task.
"Heater1ControlTask", // Text name for the task.
128, // Stack size in words, not bytes
(void *) &heater1, // Parameter passed into the task.
1, // Priority at which the task is created.
&taskHandle); // Used to pass out the created task's handle.
When I step through this code in debug mode, I can see that it is the fake version of xCreateTask which is being called, and the return sequence is exactly as I have specified.
However, the second test, which is not working, is as follows:
TEST(HeaterTestGroup, InitPWMTest)
{
TIM_HandleTypeDef pTimer;
HAL_StatusTypeDef halReturnOK = HAL_OK;
SET_RETURN_SEQ(HAL_TIM_Base_Init, &halReturnOK, 1);
CHECK_EQUAL(InitialisePwmTimer(&pTimer), SUCCESS);
}
This function under test, contains the following:
ErrorStatus InitialisePwmTimer(TIM_HandleTypeDef* const pTimerHandle)
{
ErrorStatus PWMInitState = SUCCESS;
pTimerHandle->Init.Prescaler = 1;
pTimerHandle->Init.CounterMode = TIM_COUNTERMODE_UP;
pTimerHandle->Init.Period = PWMPeriod;
pTimerHandle->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
pTimerHandle->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(pTimerHandle) != HAL_OK)
{
PWMInitState = ERROR;
}
...
If I step through this test in debug mode, I can see that the function calls the real function, defined in stm32f1xx_hal_tim.c, instead of calling my Fake.
I cannot see any reason why one of these would work and the other would not. Could anyone suggest a reason?
It seems that the issue is that you are calling the test function HAL_TIM_Base_Init (which you mocked) from another function - which I assume is located on ANOTHER c/cpp file and not in the same cpp file as where you defined FAKE_VALUE_FUNC(HAL_StatusTypeDef, HAL_TIM_Base_Init, TIM_HandleTypeDef*);
The issue is that by using FAKE_VALUE_FUNC you are declaring the mock function only locally in that file. However, the original function is still in your code. and is visible to all the files in your code that included the header file that declares the original function. So when you call InitialisePwmTimer you leave the test file and go "out" to the rest of the code where the original HAL_TIM_Base_Init prevails.
I offer two solutions:
Exclude from your unit tests project the C file that contains the definition (implementation) of the original function and if that is not possible try just wrapping the function with #ifdef so that it won't be included in the unit test project. But in any case, keep the header file. Then replace the use of FAKE_VALUE_FUNC with DECLARE_FAKE_VALUE_FUNC and DEFINE_FAKE_VALUE_FUNC (read more about it here: FFF Primer). This will cause your mock function to take preference and be called from outside the test file as well.
You can just use function pointer substitution. I wrote more extensively about it here: Function Pointer Substitution With FFF
I am trying to use LibTomCrypt library with Contiki OS but it's not working at all. I get the error: fatal: Not a valid object name HEAD. I have used the following code for computing hash in my client file.
unsigned char* hashSHA1(const char* input, unsigned long inputSize) {
//Initial
unsigned char* hashResult = (unsigned char*)malloc(sha1_desc.hashsize);
//Initialize a state variable for the hash
hash_state md;
sha1_init(&md);
//Process the text - remember you can call process() multiple times
sha1_process(&md, (const unsigned char*) input, inputSize);
//Finish the hash calculation
sha1_done(&md, hashResult);
// Return the result
return hashResult;
}
and then I call it in send_packet().
I have added the header file
`#include <tomcrypt.h>`
Now in Makefile, I am not sure how shall I add a path. I have checked a few possible ways, for instance, Contiki mote type creation error when trying to use libtomcrypt library (rsa public key generation) and I have added the following lines :
PROJECT_SOURCEFILES += sha1.c
MODULES += ./libtomcrypt-develop
PROJECT_LIBRARIES+= $(CONTIKI)/libtomcrypt-develop/libtomcrypt.a
(here libtomcrypt-develop is the name of the folder containing LibTomCrypt library)
According to my understanding, I guess there is something wrong in Makefile. Can someone please identify the problem in Makefile?
firstly, I have to say the dll was translated by MatLab's m file, which was compiled by c compiler using msvc_2015.
The dll was C shared library, which was said that has a common interface.
I don‘t think it's MatLab's error,because my program works.
The qt was compiled by MinGW_64_4.9.3 on my own computer,so i think qt's configuration is OK.
I can’t figure out why my program works OK, but debugging error, once I was using the fooInitialize(), there were a lot of segments error when debugging
QLibrary lib("foo.dll");
QMessageBox msg;
if(lib.load())
{
QMessageBox::information(NULL,"OK","DLL load is OK!");
Fun mlfFoo=(Fun)lib.resolve("mlfFoo"); //
Fun2 init=(Fun2)lib.resolve("fooInitialize");//
Fun2 termi=(Fun3)lib.resolve("fooTerminate");//
if (mlfFoo) //
{
QMessageBox::information(NULL,"OK","Link to Function is OK!");
init(); //
double numbrOut,*out;
double data[]={1};
mxArray* array_in,*array_out ;
array_in = mxCreateDoubleMatrix(1, 1, mxREAL);//
memcpy(mxGetPr(array_in),data , sizeof(double));
array_out=NULL;
mlfFoo(1, &array_out,array_in);
out=mxGetPr(array_out);
numbrOut=out[0];
mxDestroyArray(array_in); array_in=0;
mxDestroyArray(array_out); array_out = 0;
out=0;
if(numbrOut==10) QMessageBox::information(NULL,"NO","perfect!!!!");
termi();
}
else
QMessageBox::information(NULL,"NO","Linke to Function is not OK!!!!");
}
else
QMessageBox::information(NULL,"NO","DLL is not loaded!");`
I got this few minutes ago
"while parsing target library list: not well-formed (invalid token)"
"SuspendThread (tid=0x788) failed. (winerr 2)"
the dll's header file was made by matlab using msvc , I compared it to the samples in the matlab's document , it is the similar
I am trying to write a small extension for PostgreSQL.
As a way to test if my module loads correctly I am writing some stuff in files in the void _PG_init(void) and void _PG_fini(void) functions. Here is the code of these two functions:
#include "postgres.h"
#include "executor\executor.h"
#include "fmgr.h"
#include "funcapi.h"
#include <stdio.h>
PG_MODULE_MAGIC;
extern void _PG_init(void);
extern void _PG_fini(void);
static void myExecutorStart(QueryDesc *queryDesc, int eflags);
static void myExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count);
static void myExecutorFinish(QueryDesc *queryDesc);
static void myExecutorEnd(QueryDesc *queryDesc);
static ExecutorStart_hook_type prevExecutorStart = NULL;
static ExecutorRun_hook_type prevExecutorRun = NULL;
static ExecutorFinish_hook_type prevExecutorFinish = NULL;
static ExecutorEnd_hook_type prevExecutorEnd = NULL;
void _PG_init(void) {
FILE *file = NULL;
file = fopen("F:\\init.txt", "a+");
fprintf(file, "Init started!\n");
fclose(file);
prevExecutorStart = ExecutorStart_hook;
ExecutorStart_hook = myExecutorStart;
prevExecutorRun = ExecutorRun_hook;
ExecutorRun_hook = myExecutorRun;
prevExecutorFinish = ExecutorFinish_hook;
ExecutorFinish_hook = myExecutorFinish;
prevExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = myExecutorEnd;
}
void _PG_fini(void) {
FILE *file = NULL;
file = fopen("F:\\fini.txt", "a+");
fprintf(file, "Fini started!\n");
fclose(file);
ExecutorStart_hook = prevExecutorStart;
ExecutorRun_hook = prevExecutorRun;
ExecutorFinish_hook = prevExecutorFinish;
ExecutorEnd_hook = prevExecutorEnd;
}
Those functions are in a file called "myextension.c", compiled into "myextension.dll". I built it in Visual Studio 2015, with following settings:
Configuration Properties -> General, “Configuration Type” = “Dynamic
Library (.dll)”.
C/C++ -> Code Generation, “Enable C++ Exceptions” = “No”,“Advanced”
set “Compile As” = “Compile as C Code (/TC)”.
Linker -> Manifest File, “Generate Manifest” = “No”.
Linker -> Input -> Additional Dependencies, added “postgres.lib” to the
library list.
Configuration Properties -> C/C++ -> General, Additional Include
Directories, added: “include\server\port\win32_msvc”, “include\server\port\win32”, “include\server”, “include”
Solution configuration = Release
Solution Platform = x64 (Installed 64 bit version of PostgreSQL 9.6 on
Windows 10)
In myExecutorXXX functions I check if there are previous ExecutorXXX functions, call them if they exist, if they don't I call the standard_ExecutorXXX function. Here is an example of one of the functions:
static void myExecutorStart(QueryDesc *queryDesc, int eflags) {
if (prevExecutorStart) prevExecutorStart(queryDesc, eflags);
else standard_ExecutorStart(queryDesc, eflags);
FILE *file = NULL;
file = fopen("F:\\query.txt", "a+");
fprintf(file, "Query: %s started!\n", queryDesc->sourceText);
fclose(file);
}
I copied the "myextension.dll" in "../PostgreSQL/9.6/lib" directory, and added a "myextension.control" and "myextension--1.0.sql" to "../PostgreSQL/9.6/share/extension" directory.
myextension.control:
# pg_extension extension
comment = 'myextension!!!'
default_version = '1.0'
myextension--1.0.sql:
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION myextension" to load this file. \quit
In the "postgresql.conf" I added shared_preload_libraries = 'myextension'. After that I connected to a test DB and ran: CREATE EXTENSION myextension;, and restarted the server.
If anyone has any idea what might be causing this, please help.
A couple of comments to get you on the right track:
_PG_fini() will never get called, because modules don't get unloaded.
_PG_init(), however, does get called when the module is loaded. Your main question seems to be why nothing is written to F:\init.txt and other files you use for logging.
On Windows, PostgreSQL normally runs as service. I suspect that the operating system user doesn't have the privileges to write to these files. I know little about Windows and its permission management, but I notice that you do not check the return code of fopen(), so it might well have silently failed.
My recommendation is to use the logging infrastructure instead, e.g. with
elog(LOG, "Init started!");
That will write the message to the PostgreSQL server log and is much more comfortable and less error prone.
Two more comments:
There is no point in creating an extension, because your code does not provide any SQL functions. CREATE EXTENSION myextension is a no-operation.
Don't forget to restart the PostgreSQL server after changing shared_preload_libraries.
Currently trying to build a project in eclipse. The project explorer is shown below:
In cabbie.c I get the error, undefined reference to initialize..., in the code below:
#include <stdio.h>
#include <stdlib.h>
#include "../iotfclient.h"
Iotfclient client;
int rc;
int main() {
/* Setup your example here, code that should run once
*/
rc = initialize(&client, "h7dzt2", "Edison_cabquam", "notwindows95", "token", "Over_9000");
/* Code in this loop will run repeatedly
*/
for (;;) {
}
return 0;
}
The function is already defined in iotfclient.h which was included as a header file. Is it correct to define it as ../iotfclient.h? Am I supposed to make a Makefile? The function prototype in iotfclient.h is given below:
int initialize(Iotfclient *client, char *orgId, char *deviceType, char *deviceId, char *authmethod, char *authtoken);
/**
* Function used to initialize the IBM Watson IoT client using the config file which is generated when you register your device
* #param client - Reference to the Iotfclient
* #param configFilePath - File path to the configuration file
*
* #return int return code
* error codes
* CONFIG_FILE_ERROR -3 - Config file not present or not in right format
*/
This project is trying to connect the bluemix IOT Platform.
initialize() is declared in iotfclient.h. However, it's not necessary defined. In other words, the compiler knows identifier initialise stands for a function, but to create a program, you have also to tell the linker how the function works, that is, add the function body.
Try including ../iotfclient.c.
The function initialize is declared in ../iotfclient.h, it might be defined in ../iotfclient.c, but do you compile this file and link it to your project?