teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

高速化する方法を提案

2021/04/13 16:48

投稿

Hey_CH
Hey_CH

スコア437

answer CHANGED
@@ -1,45 +1,89 @@
1
1
  どういう風に使いたいか不明なので、勘ですが。
2
2
  C#から取得したbyte配列をpython側で2byte(16ビット)のint配列として扱えるよう修正[2021/04/13 10:31]
3
+ 高速化方法を見つけたので修正[2021/4/14 01:46]
3
4
  ```C#
4
5
  using System;
5
6
 
6
7
  namespace testNameSpace {
7
8
  public class testClass {
8
9
  public int testroc(ref byte[] bArray) {
9
- bArray[0] = 0x00;
10
+ for (int i = 0; i < bArray.Length; i++) {
10
- bArray[1] = 0x01;
11
- bArray[2] = 0xff;
11
+ bArray[i] = (byte)(i % 0xff);
12
- bArray[3] = 0xff;
12
+ }
13
13
  return 1;
14
14
  }
15
15
  }
16
16
  }
17
+
17
18
  ```
18
19
  dllは「TestLibraryForPython.dll」とする
20
+ 不要なprintやコメントは削除してください。
19
21
  ```python
20
22
  import clr
23
+ #import numpy as np
24
+ import datetime , struct
21
- clr.AddReference("TestLibraryForPython")
25
+ clr.AddReference('TestLibraryForPython')
22
26
  from testNameSpace import testClass
23
27
 
24
-
25
28
  def bytes_to_intarray(arr):
29
+ """#for文を使った場合(遅い)
26
30
  result = []
27
31
  for i in range(0,len(arr),2):
28
- result.append(arr[i]<<8 | arr[i+1]) #Big Endian
32
+ #result.append(arr[i]<<8|arr[i+1]) #18秒くらい
33
+ result.append(int.from_bytes([arr[i] , arr[i+1]] , 'big', signed='False')) #22秒くらい
34
+ """
35
+
36
+ """#リストの内包表記を使った場合(遅い)
37
+ #result = [arr[i]<<8|arr[i+1] for i in range(0,len(arr),2)] #18秒くらい
38
+ result = [int.from_bytes([arr[i] , arr[i+1]] , 'big', signed='False') for i in range(0,len(arr),2)] #22秒くらい
39
+ """
40
+
41
+ #struct.unpackを使った場合(Python.NETのメーリングリスト?からコピペ)
42
+ from ctypes import string_at
43
+ from System.Runtime.InteropServices import GCHandle, GCHandleType
44
+ arr_hndl = GCHandle.Alloc(arr, GCHandleType.Pinned)
45
+ try:
46
+ arr_ptr = arr_hndl.AddrOfPinnedObject().ToInt64() #32bit CPUの場合(.ToInt32())
47
+ fmt = '>' + str(int(len(arr)/2)) + 'H' #Big endianで2byteの符号なし整数 arrの長さが500の場合:'>250H'
48
+ result = struct.unpack(fmt, string_at(arr_ptr, len(arr))) #formatは公式ドキュメントに書いてある
49
+ finally:
50
+ if arr_hndl.IsAllocated: arr_hndl.Free()
51
+
52
+ """#NumPyを使った場合(importのコメントを外して使う)
53
+ from ctypes import string_at
54
+ from System.Runtime.InteropServices import GCHandle, GCHandleType
55
+ arr_hndl = GCHandle.Alloc(arr, GCHandleType.Pinned)
56
+ try:
57
+ arr_ptr = arr_hndl.AddrOfPinnedObject().ToInt64() #32bit CPUの場合(.ToInt32())
58
+ #dtypeはここがわかりやすい→https://note.nkmk.me/python-numpy-dtype-astype/
59
+ #>←はバイトオーダー(Big endian)
60
+ result = np.frombuffer(string_at(arr_ptr, len(arr)),'>u2')
61
+ finally:
62
+ if arr_hndl.IsAllocated: arr_hndl.Free()
63
+ """
64
+
29
65
  return result
30
66
 
31
67
 
32
68
  test = testClass()
33
- bs = bytes(range(4))
69
+ bs = bytes(50000000)
34
70
 
71
+ """#これは4秒くらいでできる
35
- r = test.testroc(bs)
72
+ t0 = datetime.datetime.now()
73
+ for b in bs:
74
+ b+=1;
75
+ t1 = datetime.datetime.now()
76
+ print(t1-t0)
77
+ """
36
78
 
79
+ r = test.testroc(bs) #bsのサイズがでかくなるとこれが呼ばれるまでに時間がかかる。C#用に何かやってる?
37
80
  bs = r[1]
38
- print(str(bs))
39
- for b in bs:
40
- print(type(b),isinstance(b,int),b+0xff)
41
81
 
82
+ t2 = datetime.datetime.now()
42
83
  bs2 = bytes_to_intarray(bs)
84
+ t3 = datetime.datetime.now()
85
+ print('bytes_to_intarray時間:',t3-t2)
86
+ print('変換後のサイズ:',len(bs2))
43
- print(bs2)
87
+ for i in range(0,10):
44
-
88
+ print(type(bs2[i]), struct.pack('>H',bs2[i]))
45
89
  ```

2

表現が間違っていたため修正16進数→2byte(16ビット)

2021/04/13 16:48

投稿

Hey_CH
Hey_CH

スコア437

answer CHANGED
@@ -1,5 +1,5 @@
1
1
  どういう風に使いたいか不明なので、勘ですが。
2
- C#から取得したbyte配列をpython側で16進数のint配列として扱えるよう修正[2021/04/13 10:31]
2
+ C#から取得したbyte配列をpython側で2byte(16ビット)のint配列として扱えるよう修正[2021/04/13 10:31]
3
3
  ```C#
4
4
  using System;
5
5
 

1

byte配列をint16として扱うよう修正

2021/04/13 01:33

投稿

Hey_CH
Hey_CH

スコア437

answer CHANGED
@@ -1,13 +1,15 @@
1
1
  どういう風に使いたいか不明なので、勘ですが。
2
+ C#から取得したbyte配列をpython側で16進数のint配列として扱えるよう修正[2021/04/13 10:31]
2
3
  ```C#
3
4
  using System;
4
5
 
5
6
  namespace testNameSpace {
6
7
  public class testClass {
7
8
  public int testroc(ref byte[] bArray) {
8
- bArray[0] = 0;
9
+ bArray[0] = 0x00;
9
- bArray[1] = 1;
10
+ bArray[1] = 0x01;
10
- bArray[2] = 2;
11
+ bArray[2] = 0xff;
12
+ bArray[3] = 0xff;
11
13
  return 1;
12
14
  }
13
15
  }
@@ -19,19 +21,25 @@
19
21
  clr.AddReference("TestLibraryForPython")
20
22
  from testNameSpace import testClass
21
23
 
24
+
25
+ def bytes_to_intarray(arr):
26
+ result = []
27
+ for i in range(0,len(arr),2):
28
+ result.append(arr[i]<<8 | arr[i+1]) #Big Endian
29
+ return result
30
+
31
+
22
32
  test = testClass()
23
- bs = bytes(range(3))
33
+ bs = bytes(range(4))
24
34
 
25
35
  r = test.testroc(bs)
26
36
 
27
37
  bs = r[1]
28
38
  print(str(bs))
29
39
  for b in bs:
30
- print(str(b))
40
+ print(type(b),isinstance(b,int),b+0xff)
31
41
 
32
- bs2 = bytes(bs)
42
+ bs2 = bytes_to_intarray(bs)
33
- print(str(bs2))
43
+ print(bs2)
34
44
 
35
- for b in bs2:
36
- print(str(b))
37
45
  ```