Microsoft MVP성태의 닷넷 이야기
ATL 로 만든 COM 에 문자열 전달하기! C#에서 어떻게 하나요? [링크 복사], [링크+제목 복사],
조회: 16680
글쓴 사람
vb표성백 (pyobegy at nate.com)
홈페이지
첨부 파일
 

스트링을 포함한 구조체 배열을 C# 컴포넌트에서 C++ Client로 out(또는 ref)로 넘길 수만 있으면 됩니다.


라는 글을 보게되었습니다.

자.. 무엇이 문제인지 시작해보겠습니다.

ATL 로 만든 COM 에 문자열 전달하기! C#에서 어떻게 하나요?

C# 서버부분입니다. 테스트용이고요, 컴포넌트를 사용하고 싶은게 목적입니다.
당연, 참조추가로, ATL 로 작성한 COM 의 tlb 파일을추가했고, HiServerComLib 가 추가되었습니다.

HiServerComLib.HiServerComClass Master = new HiServerComLib.HiServerComClass(); 이렇게, Master 포인터를 얻었고,

Master.FtpConnect(); 컴포넌트 함수에 아무런 인자가 전달되지 않는 함수의 호출은 아주 순조롭게 잘 호출이 됩니다.

하지만, ATL COM 에서 STDMETHOD(UpdateLog)(CHAR * AllPath, LONG * Result); 이렇게 매소드를 추가했는데,
추가할때, 인자를 설정하는 부분에서 in 형으로 CHAR * 를, out 형으로 LONG * 를 지정하였습니다.
분명, C++ 같은 과정으로 컴포넌트를 호출하면 잘 호출 됩니다. (소스코드는 아래쪽에 붙였습니다.)
그런데...
C# 에서는 에러가 발생합니다.
Master.UpdateLog("./Data/Facility/Wall/Module/DER123.jpg");
이렇게 사용하니, 안되는군요. 에러메시지는
오류 CS1502: 'HiServerComLib.IHiServerComClass.UpdateLog(ref sbyte)'에 가장 일치하는 오버로드된 메서드에 잘못된 인수가 있습니다.
오류 CS1503: '1' 인수: 'string'에서 'ref sbyte'(으)로 변환할 수 없습니다.
인자로 전달해야하는 자료형은 분명, CHAR * 라고 생각했는데, C#에서는 이런 자료형이 없는건지, 인식이 다른 방식으로 되는 것인지 알도리가 없네요. ref 참조형으로, sbyte 를 전달하라고 하는 것 같은데,
sbyte 는 1바이트 크기더라구요, singed byte -128~127 까지..
완전 답이 없죠.. 문자열을 전달해야하는데... 1바이트라니..
어떤방법을 써서 전달해야하는지, 아니면 ATL로 입력 자료형을 다른걸로 줘야하는지,,,,,
ATL 에서는 입력자료형에 제약이 있어서 그나마 문자열을 전달하기 위해 선택한것이 CHAR * 입니다.

이제 소스코드를 읽어주세요 ㅠㅠ

using System;
using System.Collections.Generic;
using System.Text;
using HiServerComLib;


namespace HiServerByCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            HiServerComLib.HiServerComClass Master = new HiServerComLib.HiServerComClass();
            Master.FtpConnect();
            Master.UpdateLog(ref string a);
            //Master.UpdateLog("./Data/Facility/Wall/Module/DER123.jpg");
           // ATL 로 COM 컴포넌트를 만들어 매쏘드이름을 FtpConnect(), UpdateLog() 로 만들었고,
          // 선언은 다음와 같습니다.
          // 두 함수 모두 LONG * 는 Out returnValue로 쓰기 때문에 신경을 쓰지 않습니다.
          // STDMETHOD(FtpConnect)(LONG* result);
          // STDMETHOD(UpdateLog)(CHAR * AllPath, LONG * Result);
     // UpdateLog 함수가 문제입니다.
          // ATL 에서 정말 답답하게도, CString 이 전달이 안되더군요, 그래도 CHAR *로도 별문제없이, C++ 코드에서는 문자열 넘기면 잘 받아줍니다.
          // 문제는, C# 에서 문자열을 던질려니까 (Master.UpdateLog("./Data/Facility/Wall/Module/DER123.jpg"); 이렇게..)
          // 오류 CS1503: '1' 인수: 'string'에서 'ref sbyte'(으)로 변환할 수 없습니다. 라는 에러가 뜨는군요..
         // 당연히, C++ 코드에서 문자열 넘겨서 잘 넘어가길래, C#에서도 문자열 넘기면 될줄 알았는데...
         // 아니되는군요..
         // 어떻게 이 난관을 해쳐나가야할지 모르겠습니다.
        
        }
    }
}


참고로, ATL 에서 COM을 만들어 C++ 에서 활용하는 소스입니다. 당연 잘돌아갑니다..

#include "stdafx.h"
#include "../../HiServerCom/HiServerCom/HiServerCom.h"
#import "../../HiServerCom/HiServerCom/Debug/HiServerCom.dll"


int _tmain(int argc, _TCHAR* argv[])
{
 
 CoInitialize(NULL);
 HiServerComLib::IHiServerComClassPtr Master(__uuidof(HiServerComLib::HiServerComClass));
 Master->FtpConnect();
 Master->UpdateLog("./Data/Facility/Wall/Module/DER123.jpg");
// 문자열던져도 아주 잘돌아가죠~
// C# 에서는 어떻게 해야될까요? 제발 도와주세요!!
 

 return 1000;
}


최대한 상세하게 설명을 드린다고 드렸는데..
궁금증을 풀어주시면, 혹시 해결해주신다면!! 정말 은혜 잊지않겠습니다.















[최초 등록일: ]
[최종 수정일: 2/17/2009]


비밀번호

댓글 작성자
 



2009-02-18 09시45분
사실 char *형은 C/C++ 클라이언트에서만 인식할 수 있는 호출방식일 뿐입니다. 게다가 C/C++ 클라이언트라고 하더라도 InProc DLL로 활성화되니 그런 경우에 마샬링에 문제가 없었을 뿐이지 Local Server EXE구조였다면 문제가 발생했을 것입니다.

어쨌든, C#측에서는 정상적으로 char *을 ref sbyte로 지정하는 것이 맞습니다. char *가 문자열 배열을 뜻하는 것은 C/C++ 언어 측면에서 그러할 뿐이지, 공통 언어 규약으로 보면 단순히 char == signed byte 와 다를 것이 없고 포인터 연산이 사용되었으니 ref 가 붙은 것 뿐입니다.

이런 경우에는, 명시적으로 마샬링 과정에서 char *인자가 문자열이라는 것을 알려주어야 하며, IDL 파일 해당 메서드의 옵션에 string을 추가해 주어야 합니다.

HRESULT TestMethod([in, string] CHAR* charParameter);



kevin25

1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
5781List맨1/5/20234143List.Add("newobj") 속도는 빠른 편인지요? [11]
5780임세1/3/20234710C# 프로그래밍 10 책 구매한 사람입니다. 3부 자료는 어디서 다운 받을 수 있나요? [4]
5779이건우1/2/20233590안녕하십니까 루프안에서 메세지처리에 관하여 질문드립니다! [2]
5778이건우12/30/20224912안녕하세요 c#에서 dll참조 관련 질문드립니다. [4]
5777감사합니...12/29/20223896UI Thread에 Invoke 처리관련 궁금합니다. [3]
5776pdf맨12/28/20223654C# MouseUp Event + pdf [10]
5775민성12/28/20223440안녕하세요 Class 관련해서 예외처리를 하나로 받아낼수 있는 방법 [1]
5774중급12/27/20224256중급개발자란 어느 수준인지요? [4]
5773김영식12/26/20223752c# 압축파일 읽어 올 때 BinaryRead 한글 처리 문제 [1]
5772눈송이12/26/20223926Excel VSTO 는 왜 Net Core, Net 5, 6 버전을 사용하지 않나요? [2]
5771김훈12/26/20224016c# .net client application 망분리(내부망,외부망) 환경에서 의문의 외부사이트 호출 대기 [2]
5770lsh12/26/20223647클라우디움안에 있는 파일을 File.Copy 하고싶은데 코드로는 접근을 못하나요? [1]
5769울타리12/20/20223690Active Directory 2012R2 2016 또는 2019 마이그렝션 문의 드립니다. [1]
5768c++12/14/20224481Thread를 사용한 C++ DLL에 관련된 질문입니다. [6]파일 다운로드2
5767민성12/9/20223814안녕하세요 ashx로 화일을 저장하고 화일명을 리턴하는데요 [1]
5766김명훈12/9/20223935웹브라우저에서 묻지 않고 바로 다운로드 [2]
5765hong12/1/20224200Winform(.Net6) 클라이언트에서 SignalR Core 웹서버에 접속시 인증서 문제 [3]파일 다운로드1
5764요한11/30/20224374c++ 동일한 객체인지 비교 방법문의 [2]
5763고필석11/30/20223878시작하자마자 비정상 종료하는 프로세스에 대한 문제 해결 조언 요청 드립니다. [3]
5762흰털너부리11/30/20223863wpf mvvm ui update 로딩중 표시 [1]
5761민성11/29/20223781죄송하지만 한가지만 더 여쭈어 보겠습니다 [1]
5760민성11/29/20223687안녕하세요 [2]
5759문정환11/28/20224000c# socket 통신할때 빅엔디언으로 바꿔줘야 하나요? [1]
5758라떼11/28/20225315Linux 에서 winform UI 어플리케이션 실행하기 [3]
5757흰털너부리11/25/20224150asp.net core EF AddDbContext,AddDbContextFactory 차이점 알려주세요 [1]
5756흰털너부리11/25/20223791asp.net core web api에서 json 특정 property 무시하는 방법 문의 드립니다. System.Text.Json 사용중입니다. [1]
1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...