# How to pass Python device and dtype to C++

**URL:** <https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577>\
**Category:** C++\
**Created:** [February 13, 2020, 10:02am UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577 "2020-02-13T10:02:06Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![G.M](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/g.m/32/19266_2.png) [@G.M](https://discuss.pytorch.org/u/G.M)\
**Post date:** [February 13, 2020, 10:02am UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/1 "2020-02-13T10:02:06Z")

</div>

I’m trying to implement a C++ function that has the arguments of a Device and Dtype and will be called in Python. But I got error trying to achieve this.  
Here’s my C++ code:

```auto
#define tensor torch::Tensorv
tensor fun1(tensor x,torch::Device device,torch::Dtype dtype) {
	auto opt = torch::TensorOptions(device).dtype(dtype);
	return x.to(opt);
}

```

Here’s the Python part:

```auto
a=torch.tensor([1])
fun1(a,torch.device('cpu'),torch.float)

```

Here’s the error:

```auto
    fun1(a,torch.device('cpu'),torch.float)
TypeError: fun1(): incompatible function arguments. The following argument types are supported:
    1. (arg0: at::Tensor, arg1: c10::Device, arg2: c10::ScalarType) -> at::Tensor

Invoked with: tensor([1]), device(type='cpu'), torch.float32

```

---

<div class="post-metadata">

**Author:** ![tom](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/tom/32/3162_2.png) [@tom](https://discuss.pytorch.org/u/tom)\
**Post date:** [February 14, 2020, 9:07pm UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/2 "2020-02-14T21:07:54Z")

</div>

I don’t think this works directly right now.

If you have compiled torch yourself, you see that in torch/csrc/autograd/generated/python\_torch\_functions.cpp the factory functions take the Python objects and unpacks them.

The PyBind converters are only present for IntArrayRef and Tensor ([toch/csrc/utils/pybind.h](https://github.com/pytorch/pytorch/blob/master/torch/csrc/utils/pybind.h)). You could try to register your own for torch::Device and torch::Dtype – or submit that PR (1.5 years ago, it was only Tensors).

A standard workaround could be to just pass a (potentially empty) tensor and take the device and dtype of that.

Best regards

Thomas

---

<div class="post-metadata">

**Author:** ![G.M](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/g.m/32/19266_2.png) [@G.M](https://discuss.pytorch.org/u/G.M)\
**Post date:** [February 15, 2020, 3:13am UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/3 "2020-02-15T03:13:28Z")

</div>

Ok, thank you very much. I’ll try that.

---

<div class="post-metadata">

**Author:** ![G.M](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/g.m/32/19266_2.png) [@G.M](https://discuss.pytorch.org/u/G.M)\
**Post date:** [February 19, 2020, 12:50pm UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/4 "2020-02-19T12:50:33Z")

</div>

Actually, I found a way to pass dtype to C++.  
In TouchScript(JIT), `torch.dtype` type are treated as python `int`, which corressponds to what happens in C++, as the dtypes are all `ScalarType`. So I can just create an C++ function that takes in an integer and make it an `ScalarType` to pass the dtype. But this method can only be called in TouchScript because only in TouchScript are dtypes treated as python `int`.

---

<div class="post-metadata">

**Author:** ![kaihsinwu](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/kaihsinwu/32/36742_2.png) [@kaihsinwu](https://discuss.pytorch.org/u/kaihsinwu)\
**Post date:** [September 3, 2020, 12:02am UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/5 "2020-09-03T00:02:07Z")

</div>

It’s just an follow-up. I recently encounter the similar situation. The workaround solution that I did is to use the str() to cast the torch.dtype into a C++ string, and in the python end write a wrapper around it:

Here is the C++ part:

```auto
torch::Tensor func1(const vector<int64_t> &shape, const std::string &dtype){
   // convert the string -> torch::ScalarType here. 
   auto options = torch.TensorOptions();
   if(dtype=="torch.float32"){
       options.dtype(torch::kFloat32);
   } // ... extend this

   return torch::Tensor(shape,options);

}

```

Here is the pybind wrapper part :

```auto
PYBIND11_MODULE(cytnx,m){
    m.def("c_func1",&func1);
}

```

Here is the python module in the directory structure:  
cytnx/  
|- \_\_ init \_\_.py  
|- [the dynamic linking file compiled from pybind]

Inside \_\_ init \_\_.py:

```auto
from .cytnx import *

## this is the API expose to user
def func1(shape, dtype):
     # calling the wrapper from pybind
     return c_func1(shape,str(dtype),str(device))

```

I would hope there will be a direct support over this in the future

---

<div class="post-metadata">

**Author:** ![kaihsinwu](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/kaihsinwu/32/36742_2.png) [@kaihsinwu](https://discuss.pytorch.org/u/kaihsinwu)\
**Post date:** [September 7, 2020, 3:38am UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/6 "2020-09-07T03:38:23Z")

</div>

Another way to do this, which I realized later-on is you can pass the py::object, and then cast to the torch::Dtype (torch::ScalarType):

```auto
PYBIND11_MODULE(cytnx,m){
    m.def("func1",[](py::object dtype){
                   torch::ScalarType type = torch::python::detail::py_object_to_dtype(dtype);
             });
}

```

---

<div class="post-metadata">

**Author:** ![tom](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/tom/32/3162_2.png) [@tom](https://discuss.pytorch.org/u/tom)\
**Post date:** [September 7, 2020, 6:44am UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/7 "2020-09-07T06:44:00Z")

</div>

Thank you for sharing!

---

<div class="post-metadata">

**Author:** ![esoha-nvidia](https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/esoha-nvidia/32/68502_2.png) [@esoha-nvidia](https://discuss.pytorch.org/u/esoha-nvidia)\
**Post date:** [March 15, 2024, 4:26pm UTC](https://discuss.pytorch.org/t/how-to-pass-python-device-and-dtype-to-c/69577/8 "2024-03-15T16:26:47Z")

</div>

If you cast the object to a dtype, you should first check that the conversion is valid.

if (THPDtype\_Check(obj.ptr())) {  
torch::ScalarType scalar\_type = reinterpret\_cast\<THPDtype\*\>(obj.ptr())-\>scalar\_type;  
}
