2015-01-22 3 views
2

으로 변환 현재 일부 C++ 코드를 C# 환경으로 변환해야하는 프로젝트를 진행 중입니다. 대부분의 경우, 실제로는 꽤 간단하지만 현재는 저수준 메모리 조작 함수를 변환하고 진행 방법에 대한 불확실성이 있습니다. 는 C++ 코드에서 C++ 포인터 수학을 C#

, 나는 이런 것들의 경우 많은 (분명히 매우 단순화 된)이있어 :

void SomeFunc(unsigned char* myMemoryBlock) 
{ 
    AnotherFunc(myMemoryBlock); 

    AnotherFunc(myMemoryBlock + memoryOffset); 
} 

void AnotherFunc(unsigned char* data) 
{ 
    // Also simplified - basically, modifying the 
    // byte pointed to by data and then increasing to the next item. 
    *data = 2; 
    data++; 

    *data = 5; 
    data++; 

    // And so on... 
} 

나는 C#으로 그렇게 생각하고를, 나는 기본적으로 치료에있어 "unsigned char *"를 바이트 배열 (byte [])로 사용합니다. 그러나 포인터 연산과 비슷한 연산을 수행하는 것은 기본적으로 바이트 배열에 액세스하기위한 "currentIndex"값을 늘리는 것입니까? AnotherFunc 같은 것을 위해, 나는 시작 인덱스가 0이 아닌 경우에도 시작 인덱스를 전달해야한다는 것을 의미한다고 생각하십니까?

그냥 C#으로 수행해야하는 방법인지 또는 해당 변환을 수행하는 더 좋은 방법이 있는지 확인하고 싶습니다. 또한 현재 환경에서 "안전하지 않은"키워드를 사용할 수 없기 때문에 실제로 포인터를 사용할 수 없습니다!

+0

매번 나는 myMemoryBlock C++에서이 같은 코드를 본 적이)이있다 기본적으로 우리는 C#에서 클래스라고 부릅니다. 어쩌면이 객체를 객체로 변환하는 것이 길이다. – Hogan

+1

그래, 상황이 중요하지만 네가 한 말은 맞는 것 같아. – BWG

+0

네, "unsigned char *"를 byte [] 또는 char []로 대체 할 수 있습니다 (필요한 것에 따라 다름). 그리고 memoryoffset 대신에 인덱스를 지정하십시오 (memoryoffset에 대한 C++ -> 계산의 "char"크기에 따라 다름). – hugoterelle

답변

2

@dasblinkenlight과 마찬가지로 메모리 데이터 블록 (보통 바이트 또는 char 배열)에 대한 임의의 포인터를 처리하는 C# (및 Java) 방식은 데이터 블록에 액세스하는 메서드에 추가 offset 매개 변수를 추가하는 것입니다.

세 번째 length 매개 변수를 추가하는 것이 일반적입니다. 따라서 메모리 블록을 전달하는 방법 Foo()의 일반적인 형태는 다음과 같습니다

// Operate on 'block', starting at index 'offset', 
// for 'length' elements 
// 
int Foo(byte[] block, int offset, int length) 
{ ... } 

당신은 모든 C#을 도서관에서 여기 저기이를 참조하십시오. 2 개의 메모리 블록들 (예를 들어, 하나의 블록을 다른 블록으로 복사하거나, 하나의 블록을 다른 블록과 비교하는 등)에서 동작하는 방법에 공통적 인 또 다른 형태.전체 메모리 블록 (배열)에서 작동하도록 기대하는 방법에 대한

// Operate on blocks 'src' starting at index 'srcOff', 
// and on block 'dst' starting at 'dstOff', 
// for a total of 'length' elements 
// 
int Bar(byte[] src, int srcOff, byte[] dst, int dstOff, int length) 
{ ... } 

는, 이러한 일반적으로 다음과 같이 :

// Overloaded version of Foo() that 
// operates on the entire array 'block' 
// 
int Foo(byte[] block) 
{ 
    return Foo(block, 0, block.Length); 
} 
+0

이것은 나를 위해 트릭을했습니다! 포인터의 유형이 수행되는 수학에 영향을 미친다는 점은 분명히 드러나는 합병증입니다. 예를 들어, C++에서 부호없는 char 포인터를 증가 시키면 C#에서 바이트 오프셋을 1 씩 증가시키는 반면, C++에서 32 비트 정수 포인터를 1 씩 증가 시키면 C#에서 4 바이트 씩 바이트 오프셋이 증가합니다. – kromenak

0

C#은 포인터 연산을 방지하는 정확한 이유 (포인터 연산이 취약한 오류) 대신 포인터를 사용하지 않습니다.

일반적으로 포인터와 메모리 오프셋으로 참조되는 모든 C++ 메모리 블록은 실제로 C#의 배열로 가장 잘 번역됩니다 (따라서 C# 배열도 [0]으로 시작하는 이유입니다). 그러나 배열의 기본 배열과 동일한 형식을 유지해야합니다 데이터 - char[] 대신 byte[]입니다. 이 값은 char[]이기 때문에 함수의 전반적인 용도를 확인하고 string으로 전환하는 것이 좋습니다.

3

두 함수는 myMemoryBlock을 배열을 나타내는 것처럼 처리합니다. 이 같은 myArraymyOffset 한 쌍의 단일 myMemoryBlock 매개 변수를 대체 할 수 :

void SomeFunc(char[] myArray) 
{ 
    AnotherFunc(myArray, 0); 

    AnotherFunc(myArray, memoryOffset); 
} 

void AnotherFunc(char[] data, int offset) 
{ 
    // Also simplified - basically, modifying the 
    // byte pointed to by data and then increasing to the next item. 
    data[offset++] = 2; 
    data[offset++] = 5; 
    // And so on... 
} 

참고 : 반대로 C++ 유형 unsigned char 자주 독립의 "메모리 지정되지 않은 블록"에 대한로 사용됩니다 ("문자 데이터를 나타내는 메모리 블록"). 상황에 따라 (예 : 포인터가 반드시 문자가 아닌 메모리를 가리키는 경우) byte의 배열이 더 적절한 선택입니다.

+0

'offset = 0'을 사용하면 명시 적으로 0을 사용하지 않아도되므로 위 코드와 약간 비슷한 구문을 사용할 수 있습니다. – David

+0

@Aravol 재미있는 아이디어입니다. 그러나 배열의 일부만 API에 관심을 갖도록 호출자 측에서 포인터를 명시 적으로 바꾸기 위해 배열을 포인터로 대체하는 경우 오프셋을 기본값으로 설정하지 않습니다. – dasblinkenlight

+1

또한 C#의'char'는 C++의'char'과 다릅니다. C#에서 'char'은 유니 코드 문자를 나타내는 데 사용되는 16 비트 값입니다. 여기에'byte []'를 사용하는 것이 더 적절할 수 있지만 OP의 필요에 따라 다릅니다. – Kyle