I have a structure in C and I called that structure in my go program. If that structure throws any error it terminates my go program like below
orderbook.h
-------------
#ifndef _ORDERBOOK_H
#define _ORDERBOOK_H
typedef struct order order;
struct order {
int tradeid;
int side;
int symbol;
double amount;
double price;
};
orderbook.c
--------------
include "orderbook.h"
order* order_place(char *side,double amount,double price,char symbol[19])
{
struct order *tradeorder= calloc(1000000,sizeof(struct order));//Initlize the structure
//My internal code which place an order
clob_ord_t o=unxs_order(c, (clob_ord_t){CLOB_TYPE_LMT,parsed_side, amount, .lmt =price, .usr = (uintptr_t)out},NANPX);
if (o.qty.dis + o.qty.hid > 0.dd) {
/* put remainder of order into book */
i = clob_add(c, o);
//printf("orderid..%lu\n", i.usr);
printf("orderid..%s\n", i.usr);
insertMap(hashTable, i.usr, i);
// printMap(hashTable);
flag=true;
tradeorder[0].orderstatus=1;
tradeorder[0].orderid=offerid;
tradeorder[0].side=sid;
tradeorder[0].symbol=atoi(symbol);
tradeorder[0].amount=(double)o.qty.dis;
tradeorder[0].price=price;
}
return tradeorder; //return the structure
}
main.go
---------
o:=C.order_place(C.CString("ASK"),C.double(12.0),C.double(1.0),C.CString("1")) //this line may get an exception If some wrong parameter to pass otherwise returns correct value
If I put correct parameter to order_pace function from go there is no issue, If I pass some incorrect parameter then In get an exception an it terminates the go server. Now I need to handle that exception so that my server remain running irrespective of an exception.
You can't catch the fatal fault, and it isn't safe to continue after your C code throws a fault (unlike Go). The running program is in an undefined potentially dangerous state. The safest thing to do is shutdown the program and/or let it crash.
You must check for errors within C.order_place and return an error on failure. Eg, return NULL.
A few other recommendations:
Allocate struct order via Go to rely on the garbage collector to simplify memory management.
var order C.struct_order
C.order_place(&order, side, ...)
Always free strings allocated via C.CString once they are no longer needed.
cstr := C.CString("test")
C.free(unsafe.Pointer(cstr))
Depending on your platform, you can simplify debugging with improved stack traces by importing cgosymbolizer. This adds support for C stack traces.
import _ "github.com/ianlancetaylor/cgosymbolizer"
You probably should use char *symbol instead of char symbol[19] in your example since C.CString returns a pointer to an arbitrarily long C string, not a pointer to an array of 19 chars.
Related
We use a third party Tcl parsing library to validation Tcl script for both syntax and semantic checking. The driver was written in C and defined a set of utility functions. Then it calls Tcl_CreateObjCommand so the script could call these C functions. Now we are in the process of porting the main program to go and I could not find a way to do this. Anyone know a way to call golang functions from Tcl script?
static int
create_utility_tcl_cmds(Tcl_Interp* interp)
{
if (Tcl_CreateObjCommand(interp, "ip_v4_address",
ip_address, (ClientData)AF_INET, NULL) == NULL) {
TCL_CHECKER_TCL_CMD_EVENT(0, "ip_v4_address");
return -1;
}
.....
return 0;
}
Assuming you've set the relevant functions as exported and built the Go parts of your project as in
Using Go code in an existing C project
[…]
The important things to note are:
The package needs to be called main
You need to have a main function, although it can be empty.
You need to import the package C
You need special //export comments to mark the functions you want callable from C.
I can compile it as a C callable static library with the following command:
go build -buildmode=c-archive foo.go
Then the core of what remains to be done is to write the C glue function from Tcl's API to your Go code. That will involve a function something like:
static int ip_address_glue(
ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv) {
// Need an explicit cast; ClientData is really void*
GoInt address_family = (GoInt) clientData;
// Check for the right number of arguments
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "address");
return TCL_ERROR;
}
// Convert the argument to a Go string
GoString address;
int len;
address.p = Tcl_GetStringFromObj(objv[1], &len);
address.n = len; // This bit is hiding a type mismatch
// Do the call; I assume your Go function is called ip_address
ip_address(address_family, address);
// Assume the Go code doesn't fail, so no need to map the failure back to Tcl
return TCL_OK;
}
(Credit to https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf for providing enough information for me to work out some of the type bindings.)
That's then the function that you register with Tcl as the callback.
Tcl_CreateObjCommand(interp, "ip_v4_address", ip_address_glue, (ClientData)AF_INET, NULL);
Theoretically, a command registration can fail. Practically, that only happens when the Tcl interpreter (or a few critical namespaces within it) is being deleted.
Mapping a failure into Tcl is going to be easiest if it is encoded at the Go level as an enumeration. Probably easiest to represent success as zero. With that, you'd then do:
GoInt failure_code = ip_address(address_family, address);
switch (failure_code) {
case 0: // Success
return TCL_OK;
case 1: // First type of failure
Tcl_SetResult(interp, "failure of type #1", TCL_STATIC);
return TCL_ERROR;
// ... etc for each expected case ...
default: // Should be unreachable, yes?
Tcl_SetObjResult(interp, Tcl_ObjPrintf("unexpected failure: %d", failure_code));
return TCL_ERROR;
}
Passing back more complex return types with tuples of values (especially a combination of a success indicator and a “real” result value) should also be possible, but I've not got a Go development environment in order to probe how they're mapped at the C level.
I’m developing a system for our application to get data from an external device. As soon as I send it a specific message, it sends back short messages to us 10x/second (so about 1 message per 100 milliseconds). I’m using Boost for this communication.
The process is rather simple: I create the socket, send the message, giving it a handler for the message receive:
// Header file:
...
std::unique_ptr<boost::asio::io_service> _theIOService;
std::unique_ptr<boost::asio::ip::tcp::socket> _theSocket;
int size_of_the_data = 100;
std::vector<char> _raw_buffer = std::vector<char>(size_of_the_data);
boost::asio::mutable_buffers_1 _data_buffer = boost::asio::buffer(_raw_buffer, size_of_the_data);
...
// Implementation file:
...
void DeviceDataListener::initiateTransfer() {
// create and connect the socket up here
...
// send the message
boost::system::error_code error;
boost::asio::write(*_theSocket,
boost::asio::buffer(beginMessage),
boost::asio::transfer_all(), error);
// start the receive
auto handler = boost::bind(&SCUDataListener::dataHandler, this, _1, _2);
_theSocket->async_receive( _data_buffer, handler );
std::thread run_thread([&]{ _theIOService->run(); });
...
}
void DeviceDataListener::dataHandler (
const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes received.
) {
int foo = bytes_transferred;
// this line crashes application
char* pData = static_cast<char*>(_data_buffer.data());
}
It works, my handler gets called immediately, as it should. The problem is, I can’t get the data out of _data_buffer. This:
auto it = _data_buffer.begin();
causes a crash, even though _data_buffer is valid. This:
const char* pData = static_cast<char*>(_data_buffer.data());
won’t compile. The error is “Method 'data' could not be resolved”. The mutable_buffer_1 API says data() is a completely valid method that returns the beginning of the memory range.
Inspecting via a debugger, I can see that there is no error and I can see data as a member of _data_buffer and the memory address it contains does contain the data we’re expecting. The thing is, I can’t get to it via code. Does anyone know how to get to the data in a Boost mutable_buffers_1?
We’re using Eclipse CDT, C++11 and gcc running on Linux.
“Method 'data' could not be resolved”.
this error may be true, but it depends on what version of Boost you use. data() is member of mutable_buffer since >= 1.66 version. Because mutable_buffer is the base class for mutable_buffers_1 your code should compile if you use at least 1.66 version of Boost.
If your version is < 1.66 you should use
char* p1 = boost::asio::buffer_cast<char*>(_data_buffer);
to get the pointer to data in the buffer.
_data_buffer.begin();
you should not use begin() method, it returns pointer to mutable_buffer_1 itself. This method is used by internal functions of asio-boost library, for instance to copy sequence of buffers, then begin() points the particular buffer to be copied.
I'm trying to write a really small C extension. So I don't want to make a whole ruby class, with initializer, allocator, and so forth. All I want to do is add a static method to an existing class, method which will run an algorithm and return a result. Unfortunately, all documentation I find only speak about wrapping a C struct into a VALUE, but that's not my use case.
What I want to know : if I create a ruby object (which will allocate memory) inside my C code, and that I return it as the result of my function, will it be taken care of properly by the garbage collector, or is it going to leak ?
Example :
void Init_my_extension()
{
VALUE cFooModule;
cFooModule = rb_const_get(rb_cObject, rb_intern("Foo"));
rb_define_singleton_method(cFooModule, "big_calc", method_big_calc, 1);
}
VALUE method_big_calc(VALUE self, VALUE input)
{
VALUE result;
result = rb_ary_new();
return result;
}
Will the array that was allocated by rb_ary_new() be properly cleaned when it's not used anymore ? How is the garbage collector aware of references to this value ?
Yes, You code properly clean memory if You using rb_ary_new().
In my opinion You need answer on other question. How create you own object.
http://www.onlamp.com/pub/a/onlamp/2004/11/18/extending_ruby.html
first You must create rb_define_alloc_func(cYouObject,t_allocate);
similar this
struct stru { char a; };
void t_free(struct stru *a) { }
static VALUE t_allocate(VALUE obj) { return
Data_Wrap_Struct(obj,NULL,t_free,m); }
I was trying to understand how Linux system calls return error codes. I bumped into times() system call. This simple system call copies some data to user space and if that operation was not successful returns -EFAULT:
SYSCALL_DEFINE1(times, struct tms __user *, tbuf)
{
if (tbuf) {
struct tms tmp;
do_sys_times(&tmp);
if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
return -EFAULT;
}
force_successful_syscall_return();
return (long) jiffies_64_to_clock_t(get_jiffies_64());
}
My questions are:
Why -EFAULT? Shouldn't it be EFAULT without minus?
Is it a common to return negative error codes?
From man 2 syscalls:
Note: system calls indicate a failure by returning a negative error number to the caller; when this happens, the wrapper function negates the returned error number (to make it positive), copies it to errno, and returns -1 to the caller of the wrapper.
See also next answers:
What are the return values of system calls in Assembly?
Why doesn't a custom system call work properly with negative numbers?
Why does the following code throw an exception when getting to the second scanf_s after entering an number to put into the struct.
This by no means represents a complete linked list implementation.
Not sure how to get onto the next scanf_s when having entered the value? Any ideas?
EDIT: Updated code with suggested solution, but still get an AccessViolationException after first scanf_s
Code:
struct node
{
char name[20];
int age;
float height;
node *nxt;
};
int FillInLinkedList(node* temp)
{
int result;
temp = new node;
printf("Please enter name of the person");
result = scanf_s("%s", temp->name);
printf("Please enter persons age");
result = scanf_s("%d", &temp->age); // Exception here...
printf("Please enter persons height");
result = scanf_s("%f", &temp->height);
temp->nxt = NULL;
if (result >0)
return 1;
else return 0;
}
// calling code
int main(array<System::String ^> ^args)
{
node temp;
FillInLinkedList(&temp);
...
You are using scanf_s with incorrect parameters. Take a look at the examples in the MSDN documentation for the function. It requires that you pass in the size of the buffer after the buffer for all string or character parameters. So
result = scanf_s("%s", temp->name);
should be:
result = scanf_s("%s", temp->name, 20);
The first call to scanf_s is reading garbage off the stack because it is looking for another parameter and possibly corrupting memory.
There is no compiler error because scanf_s uses a variable argument list - the function doesn't have a fixed number of parameters so the compiler has no idea what scanf_s is expecting.
You need
result = scanf_s("%d", &temp->age);
and
result = scanf_s("%f", &temp->height);
Reason is that sscanf (and friends) requires a pointer to the output variable so it can store the result there.
BTW, you have a similar problem with the parameter temp of your function. Since you're changing the pointer (and not just the contents of what it points to), you need to pass a double pointer so that the changes will be visible outside your function:
int FillInLinkedList(node** temp)
And then of course you'll have to make the necessary changes inside the function.
scanf() stores data into variables, so you need to pass the address of the variable (or its pointer)Example:
char string[10];
int n;
scanf("%s", string); //string actually points to address of
//first element of string array
scanf("%d", &n); // &n is the address of the variable 'n'
%19c should be %s
temp->age should be &temp-age
temp->height should be &temp->height
Your compiler should be warning you
about these errors
I believe you need to pass parameters to scanf() functions by address. i.e. &temp->age
otherwise temp-age will be interpreted as a pointer, which will most likely crash your program.