문제

정적 라이브러리에 C 함수가 있습니다. 다음 인터페이스와 함께 A라고 부릅니다.

int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);

이 함수는 y a z의 값을 변경합니다 (확실합니다). Extern "C"를 사용하여 동적 C ++ 라이브러리 내에서 사용합니다.

자, 여기에 나를 괴롭히는 것이 있습니다.

  • y는 올바르게 설정되고 Z는 변경되지 않습니다. 정확히 의미하는 바는 둘 다 666의 (뾰족한) 값으로 초기화되면 y가 지적한 값은 호출 후에 변경되었지만 z가 가리키는 값 (여전히 666)은 변경되지 않았다는 것입니다.
  • C 바이너리에서 호출되면이 함수는 완벽하게 작동합니다 (Z가 가리키는 값이 수정 됨).
  • 동일한 프로토 타입을 갖는 함수가있는 더미 C 라이브러리를 만들고 동적 C ++ 라이브러리 내에서 사용하면 매우 잘 작동합니다. 동일한 변수를 재사용하여 (..) 호출하면 이전과 동일한 결과를 얻을 수 있습니다. z는 변경되지 않았습니다.

위의 요점은 그것이 내 변수 선언에 대한 어리석은 실수가 아니라는 것을 보여줍니다.

분명히 붙어 있고 C 라이브러리를 변경할 수 없습니다. 문제가 될 수있는 것에 대한 단서가 있습니까? 나는 c/c ++ 인터페이스의 문제에 대해 생각하고 있었고, 인스턴스 당 char*가 해석되는 방식에 대해 생각했다.

편집 : 마침내 문제가 무엇인지 알았습니다. 내 대답 아래를 참조하십시오.

도움이 되었습니까?

해결책 9

우선, 여러분의 도움에 감사드립니다. 당신이 나에게 준 수많은 아이디어와 단서 덕분에 나는이 문제를 마침내 정리할 수있었습니다. 당신의 조언은 내가 당연한 것으로 생각하는 것에 의문을 제기하는 데 도움이되었습니다.

내 문제에 대한 짧은 대답 : 문제는 내 C ++ 라이브러리가 이전 버전의 C 라이브러리를 사용했다는 것입니다. 이 오래된 버전은 네 번째 논쟁을 놓쳤다. 결과적으로, 네 번째 논쟁은 분명히 변하지 않았다.

나는 이것이 문제라는 것을 깨달았 기 때문에 조금 부끄럽다. 그러나 나는 내 코드가 정상으로 컴파일되고 있다는 사실에 의해 미스 슬레드였습니다. 이는 C ++ 라이브러리가 올바른 버전의 C Lib에 대해 컴파일 되었기 때문이지만 런타임에 사용중인 다른 라이브러리와 정적으로 연결된 이전 버전을 사용했습니다.

C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
     |
     ------> C lib (P) v.1.1

(n)은 (P) 버전 1.0과 정적으로 연결된 동적 라이브러리입니다. 컴파일러는 (p) 버전 1.1과 연결되어 있기 때문에 (M)에서 4 인수로 호출을 수락했지만 런타임에 (P)의 기존 버전을 사용했습니다.

이 답변이나 질문을 자유롭게 편집하거나 저에게 그렇게하도록 요청하십시오.

다른 팁

C 라이브러리와 C ++ 컴파일러가 다루는 방식의 차이점처럼 보입니다. 긴 오래. 내 생각에 C 라이브러리는 아마도 C89 이전 표준이며 실제로 64 비트를 처리한다는 것입니다. 32 비트 길이로. C ++ 라이브러리는 올바르게 처리하고 통화 스택에 64 비트를 배치하여 Y와 Z를 손상시킵니다. *int a (부호없는 int a, 부호없는 긴 b, 서명되지 않은 int *y, 부호없는 char를 통해 함수를 호출해보십시오. 지), 당신이 얻는 것을보십시오.

그냥 생각.

이것은 당신이 묘사 한 것에서 명백히 잘못된 것이없는 질문 중 하나이지만 상황이 당신이 기대하는 방식으로 작동하지 않습니다.

나는 당신이해야한다고 생각합니다 편집하다 현명한 답변을 얻기 위해 더 많은 정보를 제공하는 게시물. 특히 다음과 같이 시작하겠습니다.-

  • 이 코드는 Windows, Linux, 내장 또는 ...?
  • C 정적 라이브러리는 어떤 컴파일러와 함께 구축됩니까?
  • C ++ Dynamic 라이브러리는 어떤 컴파일러와 함께 구축됩니까?
  • 구축 된 라이브러리를 성공적으로 호출 할 수있는 C는 어떤 컴파일러입니까?
  • 소스 수준 디버거가 있습니까? 그렇다면 단계를 밟을 수 있습니다 ~ 안으로 C ++의 C 코드.

Z가 항상 지적한 데이터를 항상 수정하는 것에 대해 틀린 경우가 아니라면 문제의 원인은 매개 변수 전달 규칙 사이의 비 호환성입니다. "긴"문제는 상황이 보이지 않는다는 힌트 일 수 있습니다.

최후의 수단으로서, 분해 된 C ++ 호출 코드 (실패라고 말하는)와 C 호출 코드 (성공이라고 함)를 비교하거나 디버거를 사용하여 CPU 지침을 진행할 수 있습니다 (예, 실제로는 배울 수 있습니다. 좋은 기술과 문제 해결)

내가 아는 한, Long Long은 표준 C ++의 일부가 아니며, 아마도 그것이 당신의 문제의 원인 일 것입니다.

Dunno. a로 디버그 스텝을 시도하고 무슨 일이 일어나는지 확인하십시오 (어셈블리 코드 알림!)

C ++ 라이브러리에서 호출하는 C 라이브러리에서 원래 기능을 랩핑 할 수 있습니까?

포인트 2와 3을 기반으로하면 이것이 효과가있는 것 같습니다.

그렇지 않은 경우 더 많은 단서를 찾기 위해 또 다른 디버그 지점을 제공합니다. 실패가 먼저 팝업되는 라이브러리 중 어느 라이브러리를 확인하고 2와 3이 작동하는지 확인하지만 이것이 최소한의 차이는 무엇입니까?

또한 각 경우에 기능 통화에 의해 설정된 스택을 검사하여 다른 통화 규칙을 고려하여 차이가 있는지 확인하십시오.

1 단계 : C ++ 측에서 전달 된 포인터 Y와 Z를 C 함수에 의해 수신 된 것과 비교하십시오.

추신 : 나는 분명하게 들리고 싶지 않지만 여기서 더블 점검합니다. C 바이너리에서 호출 할 때 z가 잘 수정되었다고 말하면 Z가 가리키는 데이터가 잘 수정되었음을 의미합니다. 포인터 y와 z 자체는 가치로 전달되므로 포인터를 변경할 수 없습니다.

또 다른 거친 추측 : C 라이브러리에서 기능의 올바른 인스턴스와 연결하고 있다고 확신하십니까? 라이브러리에 사용할 수있는 몇 가지 기능이있을 수 있습니까? C에서 링커는 함수를 해결하는 방법을 결정할 때 리턴 유형 또는 매개 변수 목록에 신경 쓰지 않습니다. 이름 만 중요합니다. 따라서 이름이 같은 여러 기능이있는 경우 ...

기능의 신원을 프로그래밍 방식으로 확인할 수 있습니다. 일부 테스트 매개 변수로 기능 A를 부르는 C 라이브러리를 만들고 잘 작동하고 포인터를 기능으로 인쇄합니다. A. 라이브러리를 C ++ 앱에 연결하십시오. 그런 다음 C ++ 코드에서 볼 수있는 원래 A 함수에 대한 포인터를 인쇄하고 동일한 프로세스에서 호출 할 때 C 라이브러리에서 보는 포인터를 비교하십시오.

다시 말하지만, 명백한 것, 그러나 누가 알고 있는지 ... 당신이 호출하는 c 함수가 무국적이라고 확신합니까? 즉, 출력이 입력에만 의존한다는 것을 의미합니까? 함수가 상태가없는 경우 "숨겨진"상태가 다른 동작에 책임이있을 수 있습니다 ( zC ++ 앱에서 호출 될 때의 기능의.

C ++ 프로그램에서 프로토 타입은 extern "C"?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top