@@ -266,16 +266,16 @@ void raise_if_failed(ErlNifEnv *env, Py_ssize_t size) {
266266 }
267267}
268268
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) {
270270 Py_ssize_t size;
271271 auto buffer = PyUnicode_AsUTF8AndSize (py_object, &size);
272272 raise_if_failed (env, buffer);
273273
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) ;
279279}
280280
281281fine::Ok<> init (ErlNifEnv *env, std::string python_dl_path,
@@ -583,7 +583,7 @@ fine::Term unicode_to_string(ErlNifEnv *env, ExObject ex_object) {
583583 ensure_initialized ();
584584 auto gil_guard = PyGILGuard ();
585585
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 );
587587}
588588
589589FINE_NIF (unicode_to_string, ERL_NIF_DIRTY_JOB_CPU_BOUND);
@@ -745,7 +745,7 @@ fine::Term format_exception(ErlNifEnv *env, ExError error) {
745745 auto py_line = PyList_GetItem (py_lines, i);
746746 raise_if_failed (env, py_line);
747747
748- terms.push_back (py_object_to_binary_term (env, py_line));
748+ terms.push_back (py_str_to_binary_term (env, py_line));
749749 }
750750
751751 return enif_make_list_from_array (env, terms.data (),
@@ -803,7 +803,7 @@ fine::Term decode_once(ErlNifEnv *env, ExObject ex_object) {
803803 raise_if_failed (env, py_str);
804804 auto py_str_guard = PyDecRefGuard (py_str);
805805
806- auto binary_term = py_object_to_binary_term (env, py_str);
806+ auto binary_term = py_str_to_binary_term (env, py_str);
807807
808808 return fine::encode (
809809 env, std::make_tuple (atoms::integer, fine::Term (binary_term)));
@@ -904,7 +904,7 @@ fine::Term decode_once(ErlNifEnv *env, ExObject ex_object) {
904904 auto is_unicode = PyObject_IsInstance (py_object, py_str_type);
905905 raise_if_failed (env, is_unicode);
906906 if (is_unicode) {
907- return py_object_to_binary_term (env, py_object);
907+ return py_str_to_binary_term (env, py_object);
908908 }
909909
910910 auto py_bytes_type = PyDict_GetItemString (py_builtins, " bytes" );
@@ -917,11 +917,11 @@ fine::Term decode_once(ErlNifEnv *env, ExObject ex_object) {
917917 auto result = PyBytes_AsStringAndSize (py_object, &buffer, &size);
918918 raise_if_failed (env, result);
919919
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) ;
925925 }
926926
927927 auto py_set_type = PyDict_GetItemString (py_builtins, " set" );
@@ -1341,7 +1341,7 @@ eval(ErlNifEnv *env, ErlNifBinary code, std::string code_md5,
13411341 continue ;
13421342 }
13431343
1344- auto key_term = py_object_to_binary_term (env, py_key);
1344+ auto key_term = py_str_to_binary_term (env, py_key);
13451345 key_terms.push_back (key_term);
13461346
13471347 // Incref before making the resource
0 commit comments