$str contains "weight_\x{2639},weight_\x{c2}", what I would expect from joining "weight_\x{2639}" and "weight_\x{c2}". All I see missing is where you encod your output
# Encode input from/output to STDIN/STDOUT/STDERR as per locale
use open ':std', ':locale';
# Force UTF-8 input/output for STDIN/STDOUT/STDERR
use open ':std', ':encoding(UTF-8)';
You'll get better diagnostic output from Devel::Peek's Dump. For example, Dump($str) gives
SV = PV(0x81e829c) at 0x814ecdc
REFCNT = 1
FLAGS = (PADBUSY,PADMY,POK,pPOK,UTF8)
PV = 0x81fe838 "weight_\342\230\271,weight_\303\202"\0 [UTF8 "weight
+_\x{2639},weight_\x{c2}"]
CUR = 20
LEN = 24
You see both the external and internal representation.