문제

관리되지 않는 C ++ DLL로 C# 코드를 호출하는 것이 있습니다. 내가 호출하는 방법은 문자열을 Ref. 이것을 처리하기 위해 나는 StringBuilder를 통과 시키면, 그렇지 않으면 stackoverflowexception이 있습니다.

이것은 잘 작동하지만 일부 호출에서는 관리되지 않는 코드에서 돌아 오는 문자열이 다음과 같은 뒤죽박죽 문자열입니다. Øÿe ~., ê. 나는 이것이 인코딩과 관련이 있어야한다는 것을 알고 있지만 아래에 나열된 몇 가지를 시도했지만 아무것도 작동하지 않습니다. 이것은 VB.NET 코드에서 다른 사람이 비슷한 일을하기 위해 작성한 문제가 아닙니다.

내가 시도한 내용은 다음과 같습니다. 1. 나는 이것을 사용하고 있습니다 : [dllimport ( "dmphnx32.dll")], 성공하지 않고 모든 숯 옵션을 시도했습니다.

  1. encoding.default.getBytes, encoding.ascii, encoding.unicode 및 나머지는 성공하지 못한 상태로 사용하려고 시도했습니다.

C ++에 대한 경험이 없으므로 실제로 도움을 사용할 수 있습니다.

다음은 dllimport 방법입니다.

[DllImport("dmphnx32.dll")]
        public static extern int PhxQueryDataAttributes(int handle,
                                        StringBuilder lTableName,
                                        StringBuilder lColumnName,
                                        ref short lIteration,
                                        ref short type,
                                        ref short maxLen,
                                        ref short endorsement,
                                        StringBuilder endorsementId);

C ++ 코드는 다음과 같습니다.

short DMEXP PhxQueryDataAttributes(HWND handle,
                                   char *lTableName,
                                   char *lColumnName,
                                   short *lIteration,
                                   short *Type,
                                   short *MaxLen,
                                   short *Endorsement,
                                   char  *EndorsementID)
{

    handle = PhxInfo.HiddenHwnd;
    strcpy(lTableName, PhxInfo.TableName);
    strcpy(lColumnName, PhxInfo.ColumnName);


    *Type = PhxInfo.PhnxDataType;
    // max len
    *MaxLen = PhxInfo.MaxDataLen;
    *Endorsement = PhxInfo.Endorsement;
    strcpy(EndorsementID, PhxInfo.EndorsementID);
    // determine which table we need the iteration of
    *lIteration = PhxIterationArray[PhxInfo.sEffectiveTableID];

    return SUCCESS;
}

다음은 관리되지 않는 코드로 호출되는 C# 코드입니다.

public int PhxQueryDataAttributes(int handle, ref string lTableName, ref string lColumnName, 
            ref short lIteration, ref short type, ref short maxLen, ref short endorsement, 
            ref string endorsementId)
        {
            var sbTableName = new StringBuilder();
            var sbColName = new StringBuilder();
            var sbEndId = new StringBuilder();

            var ret = RatingProxy.PhxQueryDataAttributes(handle, sbTableName, sbColName,
            ref lIteration, ref type, ref maxLen, ref endorsement, sbEndId);


            lTableName = sbTableName.ToString();
            lColumnName = sbColName.ToString();
            endorsementId = sbEndId.ToString();
return ret;
}

고마워요, 코리

도움이 되었습니까?

해결책 3

처음 2 개의 답변을 시도하고 그들이 도움이되지 않는다는 것을 알게 된 후, 나는 다른 것이 의심되어야한다는 것을 알았습니다. 내 앱의 다른 곳에서 작은 버그를 발견하여 실제로 관리되지 않는 코드에서 초기화 매개 변수가 누락되었습니다. 이것은 이상하게 인코딩 된 문자열을 유발했습니다.

도와 주셔서 감사합니다, Corey

다른 팁

좋아, 나는 당신의 문제를 본다. 당신은 용량을 할당해야합니다 StringBuilder, 기본값 만 사용할 수 없습니다.

StringBuilder 대신 intptr 및 Marshal 클래스를 사용해 볼 수 있습니다.

따라서 다음과 같습니다.

[DllImport("dmphnx32.dll")]
    public static extern int PhxQueryDataAttributes(int handle,
                                    IntPtr lTableName,
                                    IntPtr  lColumnName,
                                    ref short lIteration,
                                    ref short type,
                                    ref short maxLen,
                                    ref short endorsement,
                                    IntPtr endorsementId);

호출 코드는 다음과 같습니다.

public int PhxQueryDataAttributes(int handle, ref string lTableName, ref string lColumnName, 
        ref short lIteration, ref short type, ref short maxLen, ref short endorsement, 
        ref string endorsementId)
    {
        var sbTableName = Marshal.AllocHGlobal(1024);//Change these to the max length possible for each string.
        var sbColName = Marshal.AllocHGlobal(1024);
        var sbEndId = = Marshal.AllocHGlobal(1024);

        var ret = RatingProxy.PhxQueryDataAttributes(handle, sbTableName, sbColName,
        ref lIteration, ref type, ref maxLen, ref endorsement, sbEndId);


        lTableName = Marshal.PtrToStringAnsi(sbTableName);
        lColumnName = Marshal.PtrToStringAnsi(sbColName);
        endorsementId = Marshal.PtrToStringAnsi(sbEndId);
        return ret;
}

이렇게하면 올바른 인코딩을 지정할 수 있습니다 (UTF 유형 인코딩이라고 가정하는 문자열 빌더로 수행 할 수 없습니다). 약간의 실험을하고 어떤 원수를 확인하십시오. ptrtoString ... ANSI는 작동하지만 대부분의 C ++ 라이브러리가 사용하기 때문입니다.

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