《-- Pro*CからPythonへの移行で学んだこと①:構造体・char配列・dataclass編 --》
Introduction / はじめに
I recently had a chance to migrate an existing Pro*C program to Python.
最近、既存のPro*CプログラムをPythonへ移行する機会がありました。
I had experience with Python, but some C-style concepts were new to me, especially structs, char arrays, memset, strcmp, atoi, and null terminators such as '\0'.
Pythonでの開発経験はありましたが、構造体、char配列、memset、strcmp、atoi、そして'\0'のような終端文字など、C言語特有の考え方には馴染みのない部分もありました。
At first, I tried to find a direct Python equivalent for each C function. However, during the migration, I realized that it is more important to understand what the original code is trying to do.
最初は、それぞれのC言語の処理に対応するPythonの書き方を探していました。しかし移行を進める中で、**「元のコードが何をしようとしているのか」**を理解することの方が重要だと気付きました。
In this article, I will introduce some common patterns I encountered when converting Pro*C code to Python.
この記事では、Pro*CからPythonへの移行で実際に出てきた、いくつかの代表的な書き換えについて紹介します。
Structs → dataclass(構造体 → dataclass)
In C, structs are often used to group multiple values together.
C言語では、複数の値をひとまとめにするために構造体がよく使われます。
For example:
例えば、次のように定義します。
typedef struct {
char year_month[7];
char item_code[8];
char quantity[12];
} ST_STOCK;
In Python, a similar structure can be represented using dataclass.
Pythonでは、dataclassを使うことで似たようなデータ構造を表現できます。
from dataclasses import dataclass
@dataclass
class Stock:
year_month: str = ""
item_code: str = ""
quantity: str = ""
Then we can create and use it like this:
作成したクラスは、次のように利用できます。
stock = Stock()
stock.year_month = "202608"
stock.item_code = "ABC001"
This keeps the structure clear while still using a Python-friendly style.
データの構造を明確に保ちながら、Pythonらしい書き方にできます。
char Arrays → str(char配列 → str)
In C, strings are often stored in fixed-size char arrays.
C言語では、文字列を固定長のchar配列として定義することがあります。
char item_code[8];
In Python, we normally do not need to define the maximum string length in advance.
Pythonでは通常、文字列の最大長をあらかじめ指定する必要はありません。
item_code: str = ""
Python manages strings dynamically, so there is no need to reserve a fixed amount of memory for the string.
Pythonでは文字列の長さが動的に管理されるため、C言語のように文字列用の固定領域をあらかじめ確保する必要はありません。
memset → Default Values(memset → 初期値)
In C, memset is often used to initialize a struct or buffer.
C言語では、構造体やバッファを初期化するためにmemsetがよく使われます。
memset(&stock, 0x00, sizeof(stock));
In Python, if default values are defined in a dataclass, creating a new instance is usually enough.
Pythonでは、dataclassに初期値を設定しておけば、新しいインスタンスを作成するだけで初期状態にできます。
stock = Stock()
The result is effectively:
実質的には、次のような状態になります。
Stock(
year_month="",
item_code="",
quantity=""
)
Key Point / ポイント
Instead of looking for a direct Python equivalent of
memset, it is better to think about whymemsetis being used.
memsetに対応するPythonの関数を探すのではなく、**「なぜここでmemsetを使っているのか」**を考えることが重要です。
If the purpose is to reset the structure, creating a new instance with default values may be the more natural Python solution.
構造体を初期状態に戻すことが目的であれば、初期値を持つ新しいインスタンスを作成する方がPythonでは自然です。
strcmp → ==
In C, string comparison often looks like this:
C言語では、文字列比較にstrcmpを使用します。
if (strcmp(item_code, "ABC001") == 0) {
}
In Python, we can simply use ==.
Pythonでは、単純に==で比較できます。
if item_code == "ABC001":
...
There is no need for a separate string comparison function.
文字列比較専用の関数を使用する必要はありません。
atoi → int
In C, atoi can be used to convert a string to an integer.
C言語では、文字列を整数へ変換するためにatoiを使用できます。
quantity = atoi(value);
In Python, we can use int().
Pythonではint()を使用します。
quantity = int(value)
However, we need to be careful with empty strings.
ただし、空文字を扱う場合には注意が必要です。
int("")
This raises the following error:
この場合、次のエラーが発生します。
ValueError: invalid literal for int() with base 10: ''
This is especially important when working with fixed-width files because a missing field or a short line may result in an empty string.
固定長ファイルでは、項目が存在しなかったりレコード長が不足していたりすると空文字になることがあるため、特に注意が必要です。
What About '\0'?('\0'はどうする?)
In C, strings are terminated by a null character.
C言語の文字列では、終端を表すためにヌル文字が使われます。
buffer[len] = '\0';
Python strings do not need a manually added null terminator because Python manages string lengths internally.
Pythonの文字列では長さが内部で管理されているため、通常は自分で終端文字を設定する必要はありません。
What I Learned / 学んだこと
The biggest lesson for me was that migrating from Pro*C to Python is not just about replacing syntax.
今回特に感じたのは、Pro*CからPythonへの移行は、単純な構文の置き換えではないということです。
Instead of asking "How do I write this C code in Python?", it is often better to ask "What is this code trying to do?"
「このCコードをPythonでどう書くか?」ではなく、「このコードは何をするために存在するのか?」と考えることが重要です。
Understanding the intent behind the original code makes it easier to write code that feels natural in Python.
元のコードの目的を理解することで、よりPythonらしい実装へ置き換えやすくなります。