どういう風に使いたいか不明なので、勘ですが。
C#から取得したbyte配列をpython側で2byte(16ビット)のint配列として扱えるよう修正[2021/04/13 10:31]
高速化方法を見つけたので修正[2021/4/14 01:46]
C#
1 using System ;
2
3 namespace 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
1 import clr
2 #import numpy as np
3 import datetime , struct
4 clr . AddReference ( 'TestLibraryForPython' )
5 from testNameSpace import testClass
6
7 def 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
47 test = testClass ( )
48 bs = bytes ( 50000000 )
49
50 """#これは4秒くらいでできる
51 t0 = datetime.datetime.now()
52 for b in bs:
53 b+=1;
54 t1 = datetime.datetime.now()
55 print(t1-t0)
56 """
57
58 r = test . testroc ( bs ) #bsのサイズがでかくなるとこれが呼ばれるまでに時間がかかる。C#用に何かやってる?
59 bs = r [ 1 ]
60
61 t2 = datetime . datetime . now ( )
62 bs2 = bytes_to_intarray ( bs )
63 t3 = datetime . datetime . now ( )
64 print ( 'bytes_to_intarray時間:' , t3 - t2 )
65 print ( '変換後のサイズ:' , len ( bs2 ) )
66 for i in range ( 0 , 10 ) :
67 print ( type ( bs2 [ i ] ) , struct . pack ( '>H' , bs2 [ i ] ) )