mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
A proof-of-concept opaque type.
This is just for playing around for the moment. It tries to address the situation that a bif creates a C-level data structure that is then to be manipulated with further bifs (but not with other script-level operators). There are two problems with that: - We don't have a type at the script-level to represent the created data structure. - We can't just pass C-level pointers around (say, via "any") because then garbage collection wouldn't clean up after us. This patch allows to wrap such a pointer with a record: type Foo = record { opaque: any; }; The bifs simply pass around instances of this record, while internally storing a C pointer to the data structure instance in its only field. Internally, "opaque" is an instance of a new Val-derived class OpaqueVal. It gets cleaned up via ref-counting as usual and deletes the C data structure automatically when done.
This commit is contained in:
parent
4aa844aa87
commit
17e17c0e6b
6 changed files with 104 additions and 0 deletions
|
@ -274,6 +274,10 @@ type entropy_test_result: record {
|
||||||
serial_correlation: double;
|
serial_correlation: double;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type test_object: record {
|
||||||
|
opaque: any;
|
||||||
|
};
|
||||||
|
|
||||||
# Prototypes of Bro built-in functions.
|
# Prototypes of Bro built-in functions.
|
||||||
@load strings.bif.bro
|
@load strings.bif.bro
|
||||||
@load bro.bif.bro
|
@load bro.bif.bro
|
||||||
|
|
41
src/Val.h
41
src/Val.h
|
@ -1030,6 +1030,47 @@ protected:
|
||||||
VectorType* vector_type;
|
VectorType* vector_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An opaque value of script type "any" that can only be manipulated via
|
||||||
|
// bifs. The value is a smart pointer that wraps a C pointer to an object of
|
||||||
|
// type T, which will be deleted when the value is no longer referenced. At
|
||||||
|
// the script level, the value is handled in a type-safe manner by embedding
|
||||||
|
// it into a record value.
|
||||||
|
template<class T>
|
||||||
|
class OpaqueVal : public Val {
|
||||||
|
public:
|
||||||
|
// Takes ownership of the object.
|
||||||
|
OpaqueVal(RecordType* arg_rt, T* arg_obj) : Val(TYPE_ANY)
|
||||||
|
{
|
||||||
|
obj = arg_obj;
|
||||||
|
rt = arg_rt;
|
||||||
|
rt->Ref();
|
||||||
|
|
||||||
|
assert(rt->NumFields() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
~OpaqueVal()
|
||||||
|
{
|
||||||
|
delete obj;
|
||||||
|
Unref(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
T* AsObject() { return obj; }
|
||||||
|
const T* AsObject() const { return obj; }
|
||||||
|
|
||||||
|
// This returns a ref'ed RecordVal.
|
||||||
|
RecordVal* MakeRecordVal()
|
||||||
|
{
|
||||||
|
RecordVal* rv = new RecordVal(rt);
|
||||||
|
rv->Assign(0, this);
|
||||||
|
Ref();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* obj;
|
||||||
|
RecordType* rt;
|
||||||
|
bool refed;
|
||||||
|
};
|
||||||
|
|
||||||
// Checks the given value for consistency with the given type. If an
|
// Checks the given value for consistency with the given type. If an
|
||||||
// exact match, returns it. If promotable, returns the promoted version,
|
// exact match, returns it. If promotable, returns the promoted version,
|
||||||
|
|
30
src/bro.bif
30
src/bro.bif
|
@ -3327,3 +3327,33 @@ function entropy_test_finish%(index: any%): entropy_test_result
|
||||||
delete s;
|
delete s;
|
||||||
return ent_result;
|
return ent_result;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%%{
|
||||||
|
class TestObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestObject() { fprintf(stderr, "ctor %p\n", this); }
|
||||||
|
~TestObject() { fprintf(stderr, "dtor %p\n", this); }
|
||||||
|
};
|
||||||
|
%%}
|
||||||
|
|
||||||
|
function create_test_object%(%) : test_object
|
||||||
|
%{
|
||||||
|
TestObject* obj = new TestObject;
|
||||||
|
|
||||||
|
OpaqueVal<TestObject>* v = new OpaqueVal<TestObject>(BifType::Record::test_object, obj);
|
||||||
|
RecordVal* rv = v->MakeRecordVal();
|
||||||
|
|
||||||
|
Unref(v);
|
||||||
|
return rv;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function do_something_with_test_object%(rv: test_object%) : any
|
||||||
|
%{
|
||||||
|
OpaqueVal<TestObject>* v = (OpaqueVal<TestObject>*) rv->AsRecordVal()->Lookup(0);
|
||||||
|
TestObject* obj = v->AsObject();
|
||||||
|
|
||||||
|
fprintf(stderr, "doing something with %p\n", obj);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
%}
|
||||||
|
|
|
@ -51,6 +51,8 @@ enum rpc_status %{
|
||||||
RPC_UNKNOWN_ERROR,
|
RPC_UNKNOWN_ERROR,
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
type test_object: record;
|
||||||
|
|
||||||
module Log;
|
module Log;
|
||||||
|
|
||||||
enum Writer %{
|
enum Writer %{
|
||||||
|
|
9
testing/btest/Baseline/language.opaque/output
Normal file
9
testing/btest/Baseline/language.opaque/output
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
ctor 0x673ed40
|
||||||
|
doing something with 0x673ed40
|
||||||
|
ctor 0x673b290
|
||||||
|
dtor 0x673ed40
|
||||||
|
ctor 0x6785890
|
||||||
|
dtor 0x673b290
|
||||||
|
{
|
||||||
|
[1] = [opaque=<no value description>]
|
||||||
|
}
|
18
testing/btest/language/opaque.bro
Normal file
18
testing/btest/language/opaque.bro
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
# @TEST-EXEC: bro %INPUT >output 2>&1
|
||||||
|
# @TEST-EXEC: btest-diff output
|
||||||
|
|
||||||
|
global obj: test_object;
|
||||||
|
global t: table[count] of test_object;
|
||||||
|
|
||||||
|
obj = create_test_object();
|
||||||
|
|
||||||
|
do_something_with_test_object(obj);
|
||||||
|
|
||||||
|
obj = create_test_object();
|
||||||
|
|
||||||
|
t[1] = obj;
|
||||||
|
print t;
|
||||||
|
delete t[1];
|
||||||
|
|
||||||
|
obj = create_test_object();
|
Loading…
Add table
Add a link
Reference in a new issue