@@ -266,16 +266,16 @@ void raise_if_failed(ErlNifEnv *env, Py_ssize_t size) {
266
266
}
267
267
}
268
268
269
- ERL_NIF_TERM py_object_to_binary_term (ErlNifEnv *env, PyObjectPtr py_object) {
269
+ ERL_NIF_TERM py_str_to_binary_term (ErlNifEnv *env, PyObjectPtr py_object) {
270
270
Py_ssize_t size;
271
271
auto buffer = PyUnicode_AsUTF8AndSize (py_object, &size);
272
272
raise_if_failed (env, buffer);
273
273
274
- ERL_NIF_TERM binary_term;
275
- auto data = enif_make_new_binary (env, size, &binary_term);
276
- memcpy (data, buffer, size );
277
-
278
- return binary_term ;
274
+ // The buffer is immutable and lives as long as the Python object,
275
+ // so we create the term as a resource binary to make it zero-copy.
276
+ Py_IncRef (py_object );
277
+ auto ex_object_resource = fine::make_resource<ExObjectResource>(py_object);
278
+ return fine::make_resource_binary (env, ex_object_resource, buffer, size) ;
279
279
}
280
280
281
281
fine::Ok<> init (ErlNifEnv *env, std::string python_dl_path,
@@ -583,7 +583,7 @@ fine::Term unicode_to_string(ErlNifEnv *env, ExObject ex_object) {
583
583
ensure_initialized ();
584
584
auto gil_guard = PyGILGuard ();
585
585
586
- return py_object_to_binary_term (env, ex_object.resource ->py_object );
586
+ return py_str_to_binary_term (env, ex_object.resource ->py_object );
587
587
}
588
588
589
589
FINE_NIF (unicode_to_string, ERL_NIF_DIRTY_JOB_CPU_BOUND);
@@ -745,7 +745,7 @@ fine::Term format_exception(ErlNifEnv *env, ExError error) {
745
745
auto py_line = PyList_GetItem (py_lines, i);
746
746
raise_if_failed (env, py_line);
747
747
748
- terms.push_back (py_object_to_binary_term (env, py_line));
748
+ terms.push_back (py_str_to_binary_term (env, py_line));
749
749
}
750
750
751
751
return enif_make_list_from_array (env, terms.data (),
@@ -803,7 +803,7 @@ fine::Term decode_once(ErlNifEnv *env, ExObject ex_object) {
803
803
raise_if_failed (env, py_str);
804
804
auto py_str_guard = PyDecRefGuard (py_str);
805
805
806
- auto binary_term = py_object_to_binary_term (env, py_str);
806
+ auto binary_term = py_str_to_binary_term (env, py_str);
807
807
808
808
return fine::encode (
809
809
env, std::make_tuple (atoms::integer, fine::Term (binary_term)));
@@ -904,7 +904,7 @@ fine::Term decode_once(ErlNifEnv *env, ExObject ex_object) {
904
904
auto is_unicode = PyObject_IsInstance (py_object, py_str_type);
905
905
raise_if_failed (env, is_unicode);
906
906
if (is_unicode) {
907
- return py_object_to_binary_term (env, py_object);
907
+ return py_str_to_binary_term (env, py_object);
908
908
}
909
909
910
910
auto py_bytes_type = PyDict_GetItemString (py_builtins, " bytes" );
@@ -917,11 +917,11 @@ fine::Term decode_once(ErlNifEnv *env, ExObject ex_object) {
917
917
auto result = PyBytes_AsStringAndSize (py_object, &buffer, &size);
918
918
raise_if_failed (env, result);
919
919
920
- ERL_NIF_TERM binary_term;
921
- auto data = enif_make_new_binary (env, size, &binary_term);
922
- memcpy (data, buffer, size );
923
-
924
- return binary_term ;
920
+ // The buffer is immutable and lives as long as the Python object,
921
+ // so we create the term as a resource binary to make it zero-copy.
922
+ Py_IncRef (py_object );
923
+ auto ex_object_resource = fine::make_resource<ExObjectResource>(py_object);
924
+ return fine::make_resource_binary (env, ex_object_resource, buffer, size) ;
925
925
}
926
926
927
927
auto py_set_type = PyDict_GetItemString (py_builtins, " set" );
@@ -1341,7 +1341,7 @@ eval(ErlNifEnv *env, ErlNifBinary code, std::string code_md5,
1341
1341
continue ;
1342
1342
}
1343
1343
1344
- auto key_term = py_object_to_binary_term (env, py_key);
1344
+ auto key_term = py_str_to_binary_term (env, py_key);
1345
1345
key_terms.push_back (key_term);
1346
1346
1347
1347
// Incref before making the resource
0 commit comments