質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

3296閲覧

Pythonで.NETの配列の使用方法

lovebeer

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2021/04/12 08:22

編集2021/04/12 23:48

.NET(C#)で作成されたライブラリの関数を呼び出すのに参照渡しした配列の扱い方が分かりません。
戻ってきたSystem.byte型の配列をPython側でint16型の配列として使用するにはどうすればいいでしょうか?
.NETの呼び出しはclrを使用しています。

該当のソースコード

C#

1// 該当関数の仕様 2class testClass 3{ 4public int testroc1(ref byte [] bArray) 5{ 6// 配列に代入している値は適当 7bArray[0] = 0; 8bArray[1] = 1; 91011bArray[999] = 10; 12 13return 1; 14} 15public int testroc1(ref short [] wArray) 16{ 17// 配列に代入している値は適当 18wArray[0] = 0; 19wArray[1] = 1; 202122wArray[999] = 10; 23 24return 1; 25} 26}

Python

1import clr 2 3test = testClass() 4bArray = [255] * (1000) 5 6ret = test.testroc1(bArray) 7 8#参照渡ししたbArray配列の内容をint16型の配列wArrayに変換 9 10ret = test.testroc1(wArray) 11 12#wArrayに格納されているデータを解析 13

ret[1]
に参照渡しした配列があると思うのですがそれをPython 側でbyte方、int16型の配列として使用する方法が分かりません。
どなたかご存じの方、回答いただけると幸いです。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/04/12 10:33

Python3.xで.NETのライブラリを呼んだりする方法はPythonが元から持っている機能ではないはずなので、質問内容が唐突過ぎる感があります。質問者さんが使っている環境を詳細に示した方が良いと思います。例えばPython.NET(pythonnet)などでしょうか。
lovebeer

2021/04/12 23:48

説明不足で申し訳ありません。 詳細について追記しました。
guest

回答1

0

ベストアンサー

どういう風に使いたいか不明なので、勘ですが。
C#から取得したbyte配列をpython側で2byte(16ビット)のint配列として扱えるよう修正[2021/04/13 10:31]
高速化方法を見つけたので修正[2021/4/14 01:46]

C#

1using System; 2 3namespace testNameSpace { 4 public class testClass { 5 public int testroc(ref byte[] bArray) { 6 for (int i = 0; i < bArray.Length; i++) { 7 bArray[i] = (byte)(i % 0xff); 8 } 9 return 1; 10 } 11 } 12} 13

dllは「TestLibraryForPython.dll」とする
不要なprintやコメントは削除してください。

python

1import clr 2#import numpy as np 3import datetime , struct 4clr.AddReference('TestLibraryForPython') 5from testNameSpace import testClass 6 7def bytes_to_intarray(arr): 8 """#for文を使った場合(遅い) 9 result = [] 10 for i in range(0,len(arr),2): 11 #result.append(arr[i]<<8|arr[i+1]) #18秒くらい 12 result.append(int.from_bytes([arr[i] , arr[i+1]] , 'big', signed='False')) #22秒くらい 13 """ 14 15 """#リストの内包表記を使った場合(遅い) 16 #result = [arr[i]<<8|arr[i+1] for i in range(0,len(arr),2)] #18秒くらい 17 result = [int.from_bytes([arr[i] , arr[i+1]] , 'big', signed='False') for i in range(0,len(arr),2)] #22秒くらい 18 """ 19 20 #struct.unpackを使った場合(Python.NETのメーリングリスト?からコピペ) 21 from ctypes import string_at 22 from System.Runtime.InteropServices import GCHandle, GCHandleType 23 arr_hndl = GCHandle.Alloc(arr, GCHandleType.Pinned) 24 try: 25 arr_ptr = arr_hndl.AddrOfPinnedObject().ToInt64() #32bit CPUの場合(.ToInt32()) 26 fmt = '>' + str(int(len(arr)/2)) + 'H' #Big endianで2byteの符号なし整数 arrの長さが500の場合:'>250H' 27 result = struct.unpack(fmt, string_at(arr_ptr, len(arr))) #formatは公式ドキュメントに書いてある 28 finally: 29 if arr_hndl.IsAllocated: arr_hndl.Free() 30 31 """#NumPyを使った場合(importのコメントを外して使う) 32 from ctypes import string_at 33 from System.Runtime.InteropServices import GCHandle, GCHandleType 34 arr_hndl = GCHandle.Alloc(arr, GCHandleType.Pinned) 35 try: 36 arr_ptr = arr_hndl.AddrOfPinnedObject().ToInt64() #32bit CPUの場合(.ToInt32()) 37 #dtypeはここがわかりやすい→https://note.nkmk.me/python-numpy-dtype-astype/ 38 #>←はバイトオーダー(Big endian) 39 result = np.frombuffer(string_at(arr_ptr, len(arr)),'>u2') 40 finally: 41 if arr_hndl.IsAllocated: arr_hndl.Free() 42 """ 43 44 return result 45 46 47test = testClass() 48bs = bytes(50000000) 49 50"""#これは4秒くらいでできる 51t0 = datetime.datetime.now() 52for b in bs: 53 b+=1; 54t1 = datetime.datetime.now() 55print(t1-t0) 56""" 57 58r = test.testroc(bs) #bsのサイズがでかくなるとこれが呼ばれるまでに時間がかかる。C#用に何かやってる? 59bs = r[1] 60 61t2 = datetime.datetime.now() 62bs2 = bytes_to_intarray(bs) 63t3 = datetime.datetime.now() 64print('bytes_to_intarray時間:',t3-t2) 65print('変換後のサイズ:',len(bs2)) 66for i in range(0,10): 67 print(type(bs2[i]), struct.pack('>H',bs2[i]))

投稿2021/04/12 11:35

編集2021/04/13 16:48
Hey_CH

総合スコア437

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lovebeer

2021/04/12 23:51

ご回答ありがとうございます。 また、こちらの説明不足で申し訳ありません。 配列に入ったデータは文字ではなく数値として扱いたいのです。。。
Hey_CH

2021/04/13 01:40

byte配列を16ビットのint配列として扱いのかな?と予想して修正しました。
lovebeer

2021/04/13 05:05

回答ありがとうございます。 おかげさまでやりたいことができました。 しかし… 実際の配列はもっと要素数が大きいことも考慮しないといけません。 50000000の場合もあります。 実際に50000000の要素数で試すとbytes_to_intarrayのところでかなり時間がかかってしまいます。 testroc1の参照型引数をint16の配列としてPython側でキャストのような形でint16型配列に変換することはできないでしょうか?
lovebeer

2021/04/14 01:46

高速化、いろいろな方法試していただきありがとうございます。 おかげさまで意図する動作が許容するスピードできるようになりました。 こちらの情報が不足していたにも関わらずご教示いただきありがとうございました。
lovebeer

2021/04/14 01:50

>Zuishin さん Python側でコピーしたいのですが、Python側でBuffer.BlockCopyは、使えるのでしょうか?
Hey_CH

2021/04/14 02:18

Zuishinさん、lovebeerさん Buffer.BlockCopyを使おうとしてみたのですが、Array dst にPythonのbytesやlistを使用することができず from System import Buffer,Byte,Array tmp = Array[Byte](bytes(len(arr))) Buffer.BlockCopy(arr,0,tmp,0,len(arr)) fmt = '>' + str(int(len(arr)/2)) + 'H' tmp = bytes(tmp) result = struct.unpack(fmt, tmp) こんな風にしか使用することができませんでした(遅い)。(やり方がまずい可能性もありますが。)
lovebeer

2021/04/14 04:45

>Hey_CH さん BlockCopyまでありがとうございます。 Pythonは、初めて触ったのですがこれまでやってきた言語と違いすぎてわからない事だらけです。 精進しようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問