# Create a Graph in C-API, export for use in Python

**URL:** <https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376>\
**Category:** Usage\
**Tags:** C, Python\
**Created:** [30 September 2022 04:43 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376 "2022-09-30T04:43:09Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aaron\_Nowack](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/aaron_nowack/32/857_2.png) [@Aaron\_Nowack](https://igraph.discourse.group/u/Aaron_Nowack)\
**Post date:** [30 September 2022 04:43 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/1 "2022-09-30T04:43:09Z")

</div>

Hello igraph users,

I’ve been using igraph effectively for visualizing neutrons in a fission chain  
(see this tweet of mine [https://twitter.com/abnowack/status/1574508829647118337](https://twitter.com/abnowack/status/1574508829647118337))

I would like to speed this process up. Currently on the C side, I create an igraph\_t object from a function such as “igraph\_t MyDataAnalysis(MyData \*data)”

To expose it to Python I use pybind11 to create a python dictionaries of the vertexes and edges. In a python script, this is wrapped and an igraph.IGraph object is created from the dictionaries.

Instead I would like to operate on the igraph\_t object created from my C code directly. My goal is to expose a wrapper around igraph\_t to Python, which allows me to use the IGraph python interface as well as additional compiled functions I’ve written

Is this possible? Is there an example? I’m unsure of how the “plumbing” of exposing the igraph\_t to act as igraph.Graph would work.

The reason is I am hoping to wrap the igraph\_t object for calculating some quantities, and I’d like to create scripts using that on the python side.

---

<div class="post-metadata">

**Author:** ![tamas](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/tamas/32/1261_2.png) [@tamas](https://igraph.discourse.group/u/tamas)\
**Post date:** [30 September 2022 13:31 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/2 "2022-09-30T13:31:29Z")

</div>

Hello,

I’m not sure I quite understand your use-case; do you construct your graphs on the C side first and do you want to wrap them in an “official” `igraph.Graph` object on the Python side?

The constructor on the Python side has a hidden `__ptr` argument that you can use to create a `Graph` object backed by an already-constructed `igraph_t` struct, but note that the constructed `Graph` object will then take ownership of the graph (you should not call `igraph_destroy()` on it any more). It’s not tested much as it is not being used any more in the core of the library, but it’s still there, so I’d start with this. Start reading the code of the constructor from [here](https://github.com/igraph/python-igraph/blob/master/src/_igraph/graphobject.c#L193) to understand what’s going on behind the scenes.

There’s also the other way round: if you have an `igraph.Graph` object on the Python side, it has a `_raw_pointer` hidden property that gives you the address of the wrapped `igraph_t` object, which you can then cast into an `igraph_t*` on the C side.

---

<div class="post-metadata">

**Author:** ![Aaron\_Nowack](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/aaron_nowack/32/857_2.png) [@Aaron\_Nowack](https://igraph.discourse.group/u/Aaron_Nowack)\
**Post date:** [30 September 2022 13:42 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/3 "2022-09-30T13:42:44Z")

</div>

Yes, I am constructing a graph on the C side, and want to be able to see them as igraph.Graph in Python. Going the other way as you described will also be useful.

Using the \_\_ptr argument and \_raw\_pointer property sounds promising, I will try those out!

Thanks

---

<div class="post-metadata">

**Author:** ![Aaron\_Nowack](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/aaron_nowack/32/857_2.png) [@Aaron\_Nowack](https://igraph.discourse.group/u/Aaron_Nowack)\
**Post date:** [1 October 2022 22:15 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/4 "2022-10-01T22:15:11Z")

</div>

I’m able to pass around an igraph\_t\* to and from Python/C, and I can instantiate an igraph.Graph() from it using the \_\_ptr method. I can call some functions, such as vcount(), ecount() etc, however calling other functions such as print() or add\_vertex crashes.

I’m not sure why this is, I’m still stumbling around but posting in case there’s a hint about what’s going on.

This is the relevant portion on the C/C++ side, which uses pybind11.

```auto
    m.def("test_c_to_python", []()
          {
            igraph_integer_t num_vertices = 102;
            igraph_integer_t num_edges = 101;
            igraph_real_t diameter;
            igraph_t *g = reinterpret_cast<igraph_t*>(igraph_malloc(sizeof(igraph_t)));

            igraph_rng_seed(igraph_rng_default(), 42);

            igraph_erdos_renyi_game(g, IGRAPH_ERDOS_RENYI_GNM,
                                    num_vertices, num_edges,
                                    IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);

            // print igraph vertices and edges
            std::cout << "test_c_to_python" << std::endl;
            std::cout << "vcount: " << igraph_vcount(g) << std::endl;
            std::cout << "ecount: " << igraph_ecount(g) << std::endl;

            auto c = py::capsule(g, "__igraph_t", 0);

            return c;
        });

```

And using it in Python,

```auto
>>> import fermiac, igraph             
>>> 
>>> a = fermiac.test_c_to_python()
test_c_to_python
vcount: 102
ecount: 101
>>>
>>> ga = igraph.Graph(__ptr=a)
>>>
>>> ga.vcount()
102
>>>
>>> ga.ecount()
101
>>>
>>> print(ga)

```

Python then terminates without an error message.

---

<div class="post-metadata">

**Author:** ![Aaron\_Nowack](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/aaron_nowack/32/857_2.png) [@Aaron\_Nowack](https://igraph.discourse.group/u/Aaron_Nowack)\
**Post date:** [2 October 2022 00:02 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/5 "2022-10-02T00:02:35Z")

</div>

After some digging it looks like the attr member of my created igraph\_t object is uninitialized, and that is causing at least the print statement to crash.

So my question now is simpler.

What initialization steps of an igraph\_t object are expected to have been done, when setting to an igraph.Graph object in Python?

I need some kind of vertex attributes, would I need edge and graph attributes? What functions should I be using?

---

<div class="post-metadata">

**Author:** ![Aaron\_Nowack](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/aaron_nowack/32/857_2.png) [@Aaron\_Nowack](https://igraph.discourse.group/u/Aaron_Nowack)\
**Post date:** [3 October 2022 02:36 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/6 "2022-10-03T02:36:34Z")

</div>

Spent more time reading about attributes and handlers. My understanding is that the C and Python interfaces have their own separate handlers for attributes, and they are not compatible.

I’m not sure it’s possible to do what I had planned. To create an igraph\_t object in C, with attributes and all, and be able to pass the pointer to this object to Python and igraph.Graph(\_\_ptr) and use the igraph\_t as an igraph.Graph object.

I’m also assuming it’s not possible to go the other way, to pass an igraph.Graph object from Python into a C function accepting an igraph\_t and perform operations with attributes as well.

---

<div class="post-metadata">

**Author:** ![tamas](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/tamas/32/1261_2.png) [@tamas](https://igraph.discourse.group/u/tamas)\
**Post date:** [3 October 2022 07:49 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/7 "2022-10-03T07:49:50Z")

</div>

Yes, at some point you need to decide whether you want to initialize the attribute pointer (`void* attr`) in a way that I think I would at least need to export a function from the Python interface that initializes the attribute handlers for an already-constructed graph in a way that is suitable for the Python interface. Would that solve the problem for you (at least partially)?

---

<div class="post-metadata">

**Author:** ![Aaron\_Nowack](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/aaron_nowack/32/857_2.png) [@Aaron\_Nowack](https://igraph.discourse.group/u/Aaron_Nowack)\
**Post date:** [3 October 2022 08:13 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/8 "2022-10-03T08:13:06Z")

</div>

I think that would partially solve my issue, yes. Ideally I’d like an igraph.Graph object to handle an igraph\_t with an initialized attribute pointer. This can be done using a function from the Python interface, as long as I can still manipulate them within C.

---

<div class="post-metadata">

**Author:** ![Igraph\_Newbie](https://avatars.discourse-cdn.com/v4/letter/i/b2d939/32.png) [@Igraph\_Newbie](https://igraph.discourse.group/u/Igraph_Newbie)\
**Post date:** [8 March 2024 19:04 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/9 "2024-03-08T19:04:37Z")

</div>

I was going to create a new thread, however, I found this one. And it’s identical to my question at least the end of it.  
First of all is there any updates to this? Can we use the python attributes in C or vice-versa even if its just for the native C-type’s like int or float?

Assuming it is still not possible - I see the attributes.h and attributes.c in the \_igraph folder in the python-igraph repo here [attributes.c](https://github.com/igraph/python-igraph/blob/main/src/_igraph/attributes.c). So my question is, can I use this instead of the c-igraph in my C code to get the attribute values?

If even that’s not possible, can you point me towards the code/doc where it shows how certain python side functions such as strength, distance that use edge attribute pass it to its C equivalent to get the results? So that I can try to do that, thanks!

---

<div class="post-metadata">

**Author:** ![tamas](https://yyz2.discourse-cdn.com/free1/user_avatar/igraph.discourse.group/tamas/32/1261_2.png) [@tamas](https://igraph.discourse.group/u/tamas)\
**Post date:** [13 March 2024 17:31 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/10 "2024-03-13T17:31:58Z")

</div>

> [@Igraph\_Newbie](#):
>
> First of all is there any updates to this?

No, there aren’t. The attribute handler API is undergoing a rewrite now in preparation for version 1.0 of the C core, but this use-case is not a priority at the moment. If I understand correctly, this can potentially be solved by calling into Python from C and asking Python to construct a `Graph` object, then extracting the `igraph_t` object wrapped in the `Graph` object and modifying that. Basically, whenever you want to modify the attributes from C, you need to go through Python, but it’s doable.

If this is not suitable for you, please describe your use-case in more detail so we can understandi t better.

> So my question is, can I use this instead of the c-igraph in my C code to get the attribute values?

I don’t think so. _Maybe_. The Python attribute handler starts by constructing three Python dictionaries to hold the graph, vertex and edge attributes, using `PyDict_New()`. `PyDict_New()` might assume that there is a Python interpreter running in the context of the process and/or it might want to reach out to the Python garbage collector, so trying to strip out the Python attribute handler from the context of the Python interpreter where it is assumed to live is risky at least. I wouldn’t pursue this direction if I were you.

> can you point me towards the code/doc where it shows how certain python side functions such as strength, distance that use edge attribute pass it to its C equivalent to get the results?

The implementations of these functions are in `src/_igraph/graphobject.c` in the source code of the Python interface. Try looking up `igraphmodule_Graph_strength()` for instance. The `weights` argument is converted by calling `igraphmodule_attrib_to_vector_t()`, which is a generic conversion function in `src/_igraph/convert.c`. All the other conversion functions are also there.

---

<div class="post-metadata">

**Author:** ![Igraph\_Newbie](https://avatars.discourse-cdn.com/v4/letter/i/b2d939/32.png) [@Igraph\_Newbie](https://igraph.discourse.group/u/Igraph_Newbie)\
**Post date:** [5 April 2024 19:55 UTC](https://igraph.discourse.group/t/create-a-graph-in-c-api-export-for-use-in-python/1376/11 "2024-04-05T19:55:48Z")

</div>

Thanks for your detailed reply and sorry for my delayed response.

Simplified version of my use case:

1. Program starts in Python - creates a Python igraph.
2. Calls my c-function in a .so file using Python ctypes, which performs custom graph operations (with edge weights) and returns the result to python.

I want to do these operations on c to get better performance in general but also to utilize multi-threading easily. So, the problem with the first option and the last option is that I have to depend on CPython and PyDicts/PyObjects to get the edge weight values in c. I want to avoid using CPython in my c-side of the code and not mess with GIL lock or reference counting.

My current working solution is somewhat similar to the one in `igraphmodule_Graph_strength`. But rather than using CPython to get values from Pydict, I copy the edge weights and other additional information about the graph (a minimized CSR) in Python to numpy arrays and use the numpy’s builtin [ndpointers](https://numpy.org/doc/stable/reference/routines.ctypeslib.html#numpy.ctypeslib.ndpointer) to send the array pointers to use in my c-function. This works and I don’t have to worry about ref counting or anything, but it essentially doubles the memory usage and also I am not able to use the c-igraph modules from c.

As you said this is not a priority and I get it. But I want to make the following suggestion/request anyway so that if possible you can consider it in the future.

- From my understanding the core data that is shared between Python and c versions of igraphs is an unweighted graph.
- So my suggestion is: What if there is also a separate class for weighted graphs with the weights (int or float) stored in c?
- This would mostly solve my issue as I currently only need edge weights on my C-code, but on a broader note, I would assume a weighted graph is a common enough use case that will benefit many. And as an added benefit, for functions such as strength, and distances there is no need to copy/retrieve the weights again and again.
