2009-05-22 5 views
1

VB 응용 프로그램에서 C DLL의 사용자 목록을 요청하고 있습니다.
VB에서 DLL을 몇 명의 사용자에게 물어보고 적절한 크기로 배열을 초기화합니다.
VB는 DLL 함수를 참조하여 해당 배열을 전달합니다.이 함수는 사용자 이름으로 채 웁니다.C- 문자열 배열에 대한 포인터를 선언 할 때 몇 개의 별표를 사용해야합니까?

다음과 같이 C 함수를 작성하기 시작했습니다 : foo(char **bar); 이는 문자열 배열로 처리됩니다. 그러나 나는 이미 가리키고있는 데이터를 수정하기보다는 어레이 포인트의 각 항목을 다른 C- 문자열 (char *username 링크 된 목록의 struct userlist) 목록으로 만들 예정입니다. 배열의 배열은 값에 의해 전달되고 있습니다 : 주소 목록은 복사본이 원래 데이터를 가리 키지 만 그 복사본의 주소는 호출자의 주소 목록을 변경하지 않습니다 (어쨌든 생각합니다.)). 그럼, 내가 그것을 foo(char ***bar);이라고 선언해야합니까? 이것은 문자열 배열에 대한 포인터가 될 것이므로 배열이 가리키는 문자열을 변경하면 호출자 (VB)가 사용하고있는 문자열 배열이 수정됩니다.

이 내 사용 지금까지입니다

EXPORT void __stdcall update_userlist(char ***ulist){ 

    int i = 0; 
    userlist *cur_user = userlist_head; //pointer to first item in linked list 

    for(; i < usercount_; ++i){ 
    *ulist[i] = cur_user->username; 
    cur_user = cur_user->next; 
    } 

} 

답변

4

을 일반적으로 VB 그냥 C 스타일의 ASCIIZ 문자열과 배열을 이해하지 못하기 때문에, 당신은 요구하는지 무엇을 할 간단하지.

DLL에서 BSTR의 VB SafeArray가 필요하지 않은 경우이 DLL을 채우는 데 어려움이 있습니다.

첫 번째 요소를 참조하여 VB 배열을 Long (C int) 배열로 전달하는 것이 간단하고 개별 문자열에 대한 포인터로이를 채울 수 있습니다. VB 측에서 이들을 VB 문자열에 복사 할 수 있습니다. 하지만 그 경우 C 문자열을 처리하는 사람은 언제입니까?

VB 배열을 만들어 미리 크기가 지정된 문자열로 채우는 경우 참조로 단일 VB 문자열 배열 요소를 전달할 수 없으므로 C 배열에서 SafeArray를 처리해야합니다. 메모리에 연속적으로 남아있는 문자열을 찾으십시오.

가장 안전한 방법은 DLL에서 소위 'Ansi BSTR'이라는 SafeArray를 만들고 VB에서 함수를 문자열 배열을 반환하도록 선언하는 것입니다. 배열 경계가 전체 이야기를 말해주기 때문에 두 번 호출 할 필요가 없습니다.

===== 편집 =====

VB는이 장면 뒤에 일부 부두를 수행하는 선언 된 함수에 문자열 배열을 전달합니다. 먼저 유니 코드의 모든 문자열을 일반적으로 'Ansi BSTR'로 알려진 나쁜 형태로 변환합니다. C로,이 모양과 ASCIIZ 또는 LPSTR로 취급 할 수 있다는 점을 제외하고는 일반적인 C 방법으로 생성하거나 길게 할 수 없다는 점을 제외하고는 C로만 채울 수 있습니다. C면에서 전달 된 배열은 ppSA (SAFEARRAY **). Ansi BSTR은 SafeArray의 pData 구성원이 참조하는 일련의 포인터입니다.

배열에서 하나의 문자열 (char *)을 절대 전달할 수 없으며 나머지 문자열을 메모리에서 연속적으로 찾을 수 있습니다. 배열 자체를 전달하고 SafeArray API (또는 SA 구조 지식)를 사용하여 배열 자체를 조작해야합니다.

전체적으로 최선의 옵션은이 모든 것을 DLL에서 직접 수행하는 것입니다. SafeArrayCreate를 사용하여 배열을 만든 다음 SysAllocStringByteLen을 사용하여 Ansi BSTR을 만들고 배열 문자열에 BSTR 인 4 바이트 포인터와 같은 문자열을 배치합니다. 돌아 왔을 때, VB는 그 부두를 수행하고 문자열을 유니 코드로 변환합니다.

VB에서 함수는 String()을 반환하는 것으로 선언됩니다.

+0

잘 VB는 SAFEARRAY 포인터를 기대하는 C 함수에 대한 참조를 전달하면, 내가 그런 식으로 조작 할 수 있습니까? 그리고 VB 배열에 DLL 번호를 미리 요청하여 적절한 수의 요소가 포함되어 있는지 확인한 다음 배열을 반복하고 항목을 변경하면됩니다. Longs의 VB 배열에 대해 언급 한 것이 간단하다면 BSTR이 실제로 char *이므로 String 배열도 작동합니다. 나는 규칙적인 위험한 배열을 사용하고 두 호출을하는 것이 SAFEARRAY를 만드는 것보다이 프로그램의 단순성에 더 적합하다고 생각한다. –

+0

... 내 주요 문제는 VB 배열의 문자열을 수정할 수있다. char **에 전달하지만 실제 배열을 값으로 전달하고 참조로 만 문자열을 전달하지 않을까요? 이렇게하면 배열의 복사본을 변경하는 것이므로 원본과 복사가 모두 가리키는 데이터가 아니라 다른 배열을 가리 키도록 배열을 리디렉션 할 수 없게됩니다. –

+0

아니요, 맞아요, 문자열을 전달할 수 없으며, 필수 유형 만 ...thanks –

1
(나는 여전히 아직 같은 DLL을 코딩 해요 ... 그것을 테스트 아직하지 않은, 지금까지 그것을 호출 할 VB 프런트 엔드가 없습니다)

두 개의 별표가 이동하는 길입니다.

char* // is a pointer to a char 
char** // is a pointer to a char pointer 
char*** // is a pointer to a pointer to a char pointer - e.g. multi-dimensional array (err...) 

나 자신을 혼동 한 :

+0

http://c2.com/cgi/wiki?ThreeStarProgrammer 문자 같은 건 없다 *** (물론,이,하지만 무의미) : 당신이 문자로 할 수있는 일 ** * 당신은 숯으로 할 수 있습니다 ** – Tordek

+0

http://c2.com/cgi/wiki?ThreeStarProgrammer – Dave

+0

"톱니 모양의 배열"(나는 용어라고 생각합니다)을 할 수 있다는 것에 주목해야합니다. {1, 2, 3], [1, 2], [1, 2, 3, 4, 5]와 같은 것입니다! – nevets1219

0

그럼 내가 바로 잡아 보자. 함수는 연결된 목록에 포함 된 데이터의 문자열 배열을 채 웁니다.

미리 목록의 크기를 알고 있다면 char **를 전달할 수 있지만 크기를 모를 경우 목록을 확장 할 수 있어야하는 경우 char ***가 필요합니다.

코드를 보면 코드 길이를 이미 알고있는 것처럼 보이기 때문에 함수를 호출하기 전에 올바른 길이의 배열을 할당하면됩니다.

void update_userlist(char **ulist) 
{ 
    int i = 0; 
    userlist *cur_user = userlist_head; 

    for(; i < usercount_; ++i) 
    { 
     ulist[i] = cur_user->username; // I am assuming that username is a char * 
     cur_user = cur_user->next; 
    } 
} 

// This sets up the array and calls the function. 
char **mylist = malloc(sizeof(char*) * usercount_); 
update_userlist(mylist); 

업데이트 : 여기서 포인터의 다양한 수준의 차이는 예를 들면 다음과 같습니다

  1. 공극 FUNC1이 포인터의 사본을 전달
    (숯 * 데이터) C 문자열로. 다른 문자열을 가리 키도록 포인터를 변경하면 호출하는 함수는 여전히 원래 문자열을 가리 킵니다.

  2. void func2 (char ** data)
    포인터의 복사본을 C 문자열의 포인터 배열에 전달합니다. 포인터를 배열의 문자열로 바꿀 수 있으며 배열의 복사본을 만들지 않았기 때문에 호출하는 함수의 배열은 호출자의 배열을 가리키기 때문에 변경됩니다.

  3. void func3 (char *** data)
    이것은 C 문자열에 대한 포인터 배열에 대한 포인터에 대한 포인터를 전달합니다. 이를 통해 전체 배열을 완전히 대체 할 수 있습니다. C 배열을 크기를 조정할 수 없으므로 배열을 확장해야하는 경우에만이 수준의 간접 지정이 필요합니다.

+0

배열을 채울 필요가있는 함수는 VB6에 있기 때문에 실제로 포인터를 조작 할 수는 없습니다. VB는 문자열의 수를 얻은 다음 문자열의 배열을 만듭니다 (C에서 char **와 같다고 생각합니다. 물건은 DLL을 전달할 때 COM에서 변환됩니다). –

+0

또한, 내가 ulist [i]를 바꿀 때, 나는 전달 된 임시 배열 포인터 만 바꾸고 있습니다. 그렇죠? 전달 된 원래 배열은 변경되지 않고 * ulist [i]가 가리키는 데이터 만 변경됩니다 ... 맞습니까? –

+0

char **는 배열에 대한 포인터입니다. 따라서 포인터를 해당 배열의 개별 문자열로 변경하면 원본이 변경됩니다. 배열로 만들어진 복사본이 없습니다. –

관련 문제