@@ -1374,6 +1374,9 @@ pub unsafe extern "C" fn qk_opcounts_clear(op_counts: *mut OpCounts) {
13741374mod py {
13751375 use crate :: circuit:: mut_ptr_as_ref;
13761376 use pyo3:: prelude:: * ;
1377+ use qiskit_circuit:: bit:: {
1378+ ClassicalRegister , PyClassicalRegister , PyQuantumRegister , QuantumRegister ,
1379+ } ;
13771380 use qiskit_circuit:: circuit_data:: { CircuitData , PyCircuitData } ;
13781381
13791382 /// @ingroup QkCircuit
@@ -1479,7 +1482,7 @@ mod py {
14791482 // SAFETY: per documentation, we are attached to a Python interpreter, and `ob` points to a
14801483 // valid PyObject.
14811484 unsafe {
1482- crate :: py:: borrow_map :: < PyCircuitData , CircuitData > (
1485+ crate :: py:: borrow_map_mut :: < PyCircuitData , CircuitData > (
14831486 Python :: assume_attached ( ) ,
14841487 ob,
14851488 // If in the future we change `PyCircuitData` to store an `Arc<RwLock>`, look at
@@ -1490,16 +1493,16 @@ mod py {
14901493 }
14911494 }
14921495
1493- /// @ingroup QkDag
1496+ /// @ingroup QkCircuit
14941497 /// Retrieve a `QkCircuit` pointer from a Python object.
14951498 ///
14961499 /// Note that the input to this function should _not_ be `QuantumCircuit`, but the output of
14971500 /// `QuantumCircuit._data`. This is necessary to enforce correct reference-counting semantics.
14981501 ///
14991502 /// This borrows a Python reference and extracts the `QkCircuit` pointer for it into
15001503 /// ``address``, if it is of the correct type. The returned pointer is borrowed from the
1501- /// `object` pointer. If the `` PyObject`` is not the correct type, the return value is 1 , the
1502- /// exception state of the Python interpreter is set, and `` address` ` is unchanged.
1504+ /// `object` pointer. If the `PyObject` is not the correct type, the return value is 0 , the
1505+ /// exception state of the Python interpreter is set, and `address` is unchanged.
15031506 ///
15041507 /// You must be attached to a Python interpreter to call this function.
15051508 ///
@@ -1508,7 +1511,7 @@ mod py {
15081511 ///
15091512 /// @param object A borrowed Python object.
15101513 /// @param address The location to write the output to.
1511- /// @return 0 on success, 1 on failure.
1514+ /// @return 1 on success, 0 on failure.
15121515 ///
15131516 /// # Safety
15141517 ///
@@ -1524,14 +1527,232 @@ mod py {
15241527 // SAFETY: per documentation, we are attached to a Python interpreter, `object` is a valid
15251528 // pointer to a PyObject, and `address` points to enough space to write a pointer.
15261529 unsafe {
1527- crate :: py:: convert_map :: < PyCircuitData , CircuitData > (
1530+ crate :: py:: convert_map_mut :: < PyCircuitData , CircuitData > (
15281531 Python :: assume_attached ( ) ,
15291532 object,
15301533 address,
15311534 |_py, qc| Ok ( & mut qc. inner ) ,
15321535 )
15331536 }
15341537 }
1538+
1539+ /// @ingroup QkCircuit
1540+ /// Pass ownership of a `QkQuantumRegister` object to Python.
1541+ ///
1542+ /// It is not safe to use the `QkQuantumRegister` pointer after calling this function. In
1543+ /// particular, you should not attempt to clear or free it. The caller must own the
1544+ /// `QkQuantumRegister`, not hold a borrowed reference (for example, a `QkQuantumRegister *`
1545+ /// retrieved from `qk_quantum_register_borrow_from_python` is not owned).
1546+ ///
1547+ /// @param qr The owned object.
1548+ /// @return An owned Python reference to the object.
1549+ ///
1550+ /// # Safety
1551+ ///
1552+ /// The caller must be attached to a Python interpreter. Behavior is undefined if `qr` is not
1553+ /// a valid non-null pointer to an initialized and owned `QkQuantumRegister`.
1554+ #[ unsafe( no_mangle) ]
1555+ pub unsafe extern "C" fn qk_quantum_register_to_python (
1556+ qr : * mut QuantumRegister ,
1557+ ) -> * mut :: pyo3:: ffi:: PyObject {
1558+ // SAFETY: per documentation, we are attached to a Python interpreter.
1559+ let py = unsafe { Python :: assume_attached ( ) } ;
1560+ // SAFETY: per documentation, `dag` points to owned and valid data.
1561+ let qreg = unsafe { Box :: from_raw ( mut_ptr_as_ref ( qr) ) } ;
1562+ match qreg. into_pyobject ( py) {
1563+ Ok ( ob) => ob. into_ptr ( ) ,
1564+ Err ( e) => {
1565+ e. restore ( py) ;
1566+ :: std:: ptr:: null_mut ( )
1567+ }
1568+ }
1569+ }
1570+
1571+ /// @ingroup QkCircuit
1572+ /// Retrieve a `QkQuantumRegister` pointer from a Python object.
1573+ ///
1574+ /// This borrows a Python reference and extracts the `QkQuantumRegister` pointer for it, if it
1575+ /// is of the correct type. The returned pointer is borrowed from the `ob` pointer. If the
1576+ /// `PyObject` is not the correct type, the return value is `NULL` and the exception state of
1577+ /// the Python interpreter is set.
1578+ ///
1579+ /// You must be attached to a Python interpreter to call this function.
1580+ ///
1581+ /// You can also use `qk_quantum_register_convert_from_python`, which is logically the exact
1582+ /// same as this function, but can be directly used as a "converter" function for the
1583+ /// `PyArg_Parse*` family of Python converter functions.
1584+ ///
1585+ /// @param ob A borrowed Python object.
1586+ /// @return A pointer to the native object, or `NULL` if the Python object is the wrong type.
1587+ ///
1588+ /// # Safety
1589+ ///
1590+ /// The caller must be attached to a Python interpreter. Behavior is undefined if `ob` is
1591+ /// not a valid non-null pointer to a Python object.
1592+ #[ unsafe( no_mangle) ]
1593+ #[ cfg( feature = "python_binding" ) ]
1594+ pub unsafe extern "C" fn qk_quantum_register_borrow_from_python (
1595+ ob : * mut pyo3:: ffi:: PyObject ,
1596+ ) -> * const QuantumRegister {
1597+ // SAFETY: per documentation, we are attached to a Python interpreter, and `ob` points to a
1598+ // valid PyObject.
1599+ unsafe {
1600+ crate :: py:: borrow_map :: < PyQuantumRegister , QuantumRegister > (
1601+ Python :: assume_attached ( ) ,
1602+ ob,
1603+ |_py, qr| Ok ( qr) ,
1604+ )
1605+ }
1606+ }
1607+
1608+ /// @ingroup QkCircuit
1609+ /// Retrieve a `QkQuantumRegister` pointer from a Python object.
1610+ ///
1611+ /// This borrows a Python reference and extracts the `QkQuantumRegister` pointer for it into
1612+ /// `address`, if it is of the correct type. The returned pointer is borrowed from the
1613+ /// `object` pointer. If the `PyObject` is not the correct type, the return value is 0, the
1614+ /// exception state of the Python interpreter is set, and `address` is unchanged.
1615+ ///
1616+ /// You must be attached to a Python interpreter to call this function.
1617+ ///
1618+ /// You can also use `qk_quantum_register_borrow_from_python`, which is logically the exact same
1619+ /// as this, but with a more natural signature for direct usage.
1620+ ///
1621+ /// @param object A borrowed Python object.
1622+ /// @param address The location to write the output to.
1623+ /// @return 1 on success, 0 on failure.
1624+ ///
1625+ /// # Safety
1626+ ///
1627+ /// The caller must be attached to a Python interpreter. Behavior is undefined if `object`
1628+ /// is not a valid non-null pointer to a Python object, or if `address` is not a pointer to
1629+ /// writeable data of the correct type.
1630+ #[ unsafe( no_mangle) ]
1631+ #[ cfg( feature = "python_binding" ) ]
1632+ pub unsafe extern "C" fn qk_quantum_register_convert_from_python (
1633+ object : * mut :: pyo3:: ffi:: PyObject ,
1634+ address : * mut :: std:: ffi:: c_void ,
1635+ ) -> :: std:: ffi:: c_int {
1636+ // SAFETY: per documentation, we are attached to a Python interpreter, `object` is a valid
1637+ // pointer to a PyObject, and `address` points to enough space to write a pointer.
1638+ unsafe {
1639+ crate :: py:: convert_map :: < PyQuantumRegister , QuantumRegister > (
1640+ Python :: assume_attached ( ) ,
1641+ object,
1642+ address,
1643+ |_py, qr| Ok ( qr) ,
1644+ )
1645+ }
1646+ }
1647+
1648+ /// @ingroup QkCircuit
1649+ /// Pass ownership of a `QkClassicalRegister` object to Python.
1650+ ///
1651+ /// It is not safe to use the `QkClassicalRegister` pointer after calling this function. In
1652+ /// particular, you should not attempt to clear or free it. The caller must own the
1653+ /// `QkClassicalRegister`, not hold a borrowed reference (for example, a `QkClassicalRegister *`
1654+ /// retrieved from `qk_classical_register_borrow_from_python` is not owned).
1655+ ///
1656+ /// @param cr The owned object.
1657+ /// @return An owned Python reference to the object.
1658+ ///
1659+ /// # Safety
1660+ ///
1661+ /// The caller must be attached to a Python interpreter. Behavior is undefined if `cr` is not
1662+ /// a valid non-null pointer to an initialized and owned `QkClassicalRegister`.
1663+ #[ unsafe( no_mangle) ]
1664+ pub unsafe extern "C" fn qk_classical_register_to_python (
1665+ cr : * mut ClassicalRegister ,
1666+ ) -> * mut :: pyo3:: ffi:: PyObject {
1667+ // SAFETY: per documentation, we are attached to a Python interpreter.
1668+ let py = unsafe { Python :: assume_attached ( ) } ;
1669+ // SAFETY: per documentation, `dag` points to owned and valid data.
1670+ let cr = unsafe { Box :: from_raw ( mut_ptr_as_ref ( cr) ) } ;
1671+ match cr. into_pyobject ( py) {
1672+ Ok ( ob) => ob. into_ptr ( ) ,
1673+ Err ( e) => {
1674+ e. restore ( py) ;
1675+ :: std:: ptr:: null_mut ( )
1676+ }
1677+ }
1678+ }
1679+
1680+ /// @ingroup QkCircuit
1681+ /// Retrieve a `QkClassicalRegister` pointer from a Python object.
1682+ ///
1683+ /// This borrows a Python reference and extracts the `QkClassicalRegister` pointer for it, if it
1684+ /// is of the correct type. The returned pointer is borrowed from the `ob` pointer. If the
1685+ /// `PyObject` is not the correct type, the return value is `NULL` and the exception
1686+ /// state of the Python interpreter is set.
1687+ ///
1688+ /// You must be attached to a Python interpreter to call this function.
1689+ ///
1690+ /// You can also use `qk_classical_register_convert_from_python`, which is logically the exact
1691+ /// same as this function, but can be directly used as a "converter" function for the
1692+ /// `PyArg_Parse*` family of Python converter functions.
1693+ ///
1694+ /// @param ob A borrowed Python object.
1695+ /// @return A pointer to the native object, or `NULL` if the Python object is the wrong type.
1696+ ///
1697+ /// # Safety
1698+ ///
1699+ /// The caller must be attached to a Python interpreter. Behavior is undefined if `ob` is
1700+ /// not a valid non-null pointer to a Python object.
1701+ #[ unsafe( no_mangle) ]
1702+ #[ cfg( feature = "python_binding" ) ]
1703+ pub unsafe extern "C" fn qk_classical_register_borrow_from_python (
1704+ ob : * mut pyo3:: ffi:: PyObject ,
1705+ ) -> * const ClassicalRegister {
1706+ // SAFETY: per documentation, we are attached to a Python interpreter, and `ob` points to a
1707+ // valid PyObject.
1708+ unsafe {
1709+ crate :: py:: borrow_map :: < PyClassicalRegister , ClassicalRegister > (
1710+ Python :: assume_attached ( ) ,
1711+ ob,
1712+ |_py, cr| Ok ( cr) ,
1713+ )
1714+ }
1715+ }
1716+
1717+ /// @ingroup QkCircuit
1718+ /// Retrieve a `QkClassicalRegister` pointer from a Python object.
1719+ ///
1720+ /// This borrows a Python reference and extracts the `QkClassicalRegister` pointer for it into
1721+ /// `address`, if it is of the correct type. The returned pointer is borrowed from the
1722+ /// `object` pointer. If the `PyObject` is not the correct type, the return value is 0, the
1723+ /// exception state of the Python interpreter is set, and `address` is unchanged.
1724+ ///
1725+ /// You must be attached to a Python interpreter to call this function.
1726+ ///
1727+ /// You can also use `qk_classical_register_borrow_from_python`, which is logically the exact same as this,
1728+ /// but with a more natural signature for direct usage.
1729+ ///
1730+ /// @param object A borrowed Python object.
1731+ /// @param address The location to write the output to.
1732+ /// @return 1 on success, 0 on failure.
1733+ ///
1734+ /// # Safety
1735+ ///
1736+ /// The caller must be attached to a Python interpreter. Behavior is undefined if `object`
1737+ /// is not a valid non-null pointer to a Python object, or if `address` is not a pointer to
1738+ /// writeable data of the correct type.
1739+ #[ unsafe( no_mangle) ]
1740+ #[ cfg( feature = "python_binding" ) ]
1741+ pub unsafe extern "C" fn qk_classical_register_convert_from_python (
1742+ object : * mut :: pyo3:: ffi:: PyObject ,
1743+ address : * mut :: std:: ffi:: c_void ,
1744+ ) -> :: std:: ffi:: c_int {
1745+ // SAFETY: per documentation, we are attached to a Python interpreter, `object` is a valid
1746+ // pointer to a PyObject, and `address` points to enough space to write a pointer.
1747+ unsafe {
1748+ crate :: py:: convert_map :: < PyClassicalRegister , ClassicalRegister > (
1749+ Python :: assume_attached ( ) ,
1750+ object,
1751+ address,
1752+ |_py, cr| Ok ( cr) ,
1753+ )
1754+ }
1755+ }
15351756}
15361757#[ cfg( feature = "python_binding" ) ]
15371758pub use py:: * ;
0 commit comments