By restructuring the C interface slightly we can get what I think is a much cleaner interface.
In summary all C functions return an int indicating success/failure, this means the old return values must be passed in as a pointer. We also add a function to return the error message if the call fails. Anyway here's the new header
1 #pragma once
2
3 typedef struct
4 {
5 int x;
6 int y;
7 } CLocation;
8
9 typedef struct HMyMap HMyMap;
10
11 int MyMap_create( HMyMap** );
12 void MyMap_destroy( HMyMap *h );
13
14 int MyMap_addKV( HMyMap *h, const char *k, CLocation v );
15 int MyMap_getV( HMyMap *h, const char *k, CLocation *v);
16 char* MyMap_getErrorMessage( HMyMap *h );
2
3 typedef struct
4 {
5 int x;
6 int y;
7 } CLocation;
8
9 typedef struct HMyMap HMyMap;
10
11 int MyMap_create( HMyMap** );
12 void MyMap_destroy( HMyMap *h );
13
14 int MyMap_addKV( HMyMap *h, const char *k, CLocation v );
15 int MyMap_getV( HMyMap *h, const char *k, CLocation *v);
16 char* MyMap_getErrorMessage( HMyMap *h );
And heres example code using this:
#include "simpletest.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
HMyMap *h;
if( ! MyMap_create(&h) )
{
printf("ERROR: FAILURE TO CREATE\n");
return 1;
}
CLocation loc = {2, 3};
if( ! MyMap_addKV(h, "test", loc) )
{
printf("ERROR: FAILURE %s\n", MyMap_getErrorMessage(h) );
return 1;
}
if( ! MyMap_addKV(h, "test", loc) )
{
printf("THIS SHOULD FAIL : FAILURE %s\n", MyMap_getErrorMessage(h) );
}
CLocation v;
if( ! MyMap_getV(h, "test", &v) )
{
printf("ERROR: FAILURE %s\n", MyMap_getErrorMessage(h) );
return 1;
}
printf("%s : (%d, %d)\n", "test", v.x, v.y );
CLocation w;
if( ! MyMap_getV(h, "monkey", &w) )
{
printf("THIS SHOULD FAIL: FAILURE %s\n", MyMap_getErrorMessage(h) );
}
MyMap_destroy(h);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
HMyMap *h;
if( ! MyMap_create(&h) )
{
printf("ERROR: FAILURE TO CREATE\n");
return 1;
}
CLocation loc = {2, 3};
if( ! MyMap_addKV(h, "test", loc) )
{
printf("ERROR: FAILURE %s\n", MyMap_getErrorMessage(h) );
return 1;
}
if( ! MyMap_addKV(h, "test", loc) )
{
printf("THIS SHOULD FAIL : FAILURE %s\n", MyMap_getErrorMessage(h) );
}
CLocation v;
if( ! MyMap_getV(h, "test", &v) )
{
printf("ERROR: FAILURE %s\n", MyMap_getErrorMessage(h) );
return 1;
}
printf("%s : (%d, %d)\n", "test", v.x, v.y );
CLocation w;
if( ! MyMap_getV(h, "monkey", &w) )
{
printf("THIS SHOULD FAIL: FAILURE %s\n", MyMap_getErrorMessage(h) );
}
MyMap_destroy(h);
return 0;
}
And finally an extract from the implementation:
18 struct HMyMap : public MyMap
19 {
20 HMyMap() : MyMap(), error_message() {}
21 std::string error_message;
22 };
23
24 int MyMap_create( HMyMap**h )
25 {
26 *h = new HMyMap();
27 return 1;
28 }
29
30 void MyMap_destroy( HMyMap *h )
31 {
32 delete h;
33 }
34
35 int MyMap_addKV( HMyMap *h, const char *k, CLocation v )
36 try
37 {
38 h->addKV( k, pair_from_cloc(v) );
39 return 1;
40 }
41 catch( MyMap::Exception & e )
42 {
43 h->error_message = e.mesg_;
44 return 0;
45 }
46
47 int MyMap_getV( HMyMap *h, const char *k, CLocation *v)
48 try
49 {
50 *v = cloc_from_pair( h->getV(k) );
51 return 1;
52 }
53 catch( MyMap::Exception & e )
54 {
55 h->error_message = e.mesg_;
56 return 0;
57 }
58
59 char * MyMap_getErrorMessage( HMyMap * h )
60 {
61 return const_cast<char*>(h->error_message.c_str());
62 }
19 {
20 HMyMap() : MyMap(), error_message() {}
21 std::string error_message;
22 };
23
24 int MyMap_create( HMyMap**h )
25 {
26 *h = new HMyMap();
27 return 1;
28 }
29
30 void MyMap_destroy( HMyMap *h )
31 {
32 delete h;
33 }
34
35 int MyMap_addKV( HMyMap *h, const char *k, CLocation v )
36 try
37 {
38 h->addKV( k, pair_from_cloc(v) );
39 return 1;
40 }
41 catch( MyMap::Exception & e )
42 {
43 h->error_message = e.mesg_;
44 return 0;
45 }
46
47 int MyMap_getV( HMyMap *h, const char *k, CLocation *v)
48 try
49 {
50 *v = cloc_from_pair( h->getV(k) );
51 return 1;
52 }
53 catch( MyMap::Exception & e )
54 {
55 h->error_message = e.mesg_;
56 return 0;
57 }
58
59 char * MyMap_getErrorMessage( HMyMap * h )
60 {
61 return const_cast<char*>(h->error_message.c_str());
62 }
So not much trickier than the other implementation, and now that I've built them both I consider this way of doing the wrapping to be easier to work with.
Sorry theres not much discussion of the code this time. But hopefully it will still be helpful to someone.
No comments:
Post a Comment