在Origin里調用DLL

        Origin自帶的Origin C語言允許用戶通過編程來更高效地完成大批量的作圖和數據處理。應該看到,Origin C本身有著較大的局限:不支持自定義函數返回結構體類型的數據( "Origin C doesn't support external functions that return a struct type variable", http://ocwiki.originlab.com/index.php?title=OCGuide:Calling_GNU_Scientific_Library ),在循環結構里的執行速度很慢,等。

        因此,在必要的時候,我會自己寫個DLL供Origin C調用。如在這個帖子里:http://emuch.net/bbs/viewthread.php?tid=5432435,我給出的是Origin C寫的程序,現在稍加修改以便記錄執行耗時:

#include <Origin.h>
int imp_one_line()
{
        string pstrOut;
        okutil_FileDialog(&pstrOut, FALSE);
       
        string pstrOut2;
        struct tm *nowtime;
        time_t aclock;
        time(&aclock);
        nowtime = localtime(&aclock);
        pstrOut2 = pstrOut + "-" + (nowtime->tm_year + 1900) + "-" + (nowtime->tm_mon + 1) + "-" + (nowtime->tm_mday);
        pstrOut2 = pstrOut2 + "-" + nowtime->tm_hour + "-" + nowtime->tm_min + "-" + nowtime->tm_sec + ".asc";
       
        FILE *fp1,*fp2;
        fp1 = fopen( pstrOut, "r" ) ;
        fp2 = fopen(pstrOut2, "w" ) ;
       
        fseek(fp1, 0L, SEEK_END ) ;
        int f_end = ftell(fp1);
        fseek(fp1, 0L, SEEK_SET ) ;
       
        char *chrAll = (char*)calloc(f_end+1,sizeof(char) ) ;
        if(!chrAll)
                return -1;
        fgets(chrAll,f_end,fp1 ) ;    // only ONE line of data
        MessageBox(GetWindow(), "Just for the first line of data. Please click OK to continue.","Warning!" ) ;
       
        Sleep(300 ) ;
        LT_execute("type -a Converting...." ) ;
       
        DWORD dw1 = GetTickCount();
        int lchrAll = lstrlen(chrAll ) ;
        for(int i=0;i<lchrAll;i++)
                if(44==(int)chrAll [ i ])
                        chrAll [ i ]=(char)10;
       
        fputs(chrAll,fp2 ) ;
        DWORD dw2 = GetTickCount();

        Sleep(300 ) ;
        LT_execute("type -a ....Done" ) ;
       
        printf("%d ms\n",dw2-dw1);
        
        fclose(fp1 ) ;
        fclose(fp2 ) ;
       
        Worksheet wks;
        wks.Create("origin" ) ;
        if(!wks)
                return -2;
        ASCIMP ai;
        if( 0 == AscImpReadFileStruct(pstrOut2, &ai) )
                if( 0 == wks.ImportASCII(pstrOut2, ai) )
                        out_str("Import data successful." ) ;
       
        return 0;
}
執行結果顯示:

1> imp_one_line()=
Converting....
....Done
49407 ms
Import data successful.
imp_one_line()=0

下面用調用DLL的方法來看看執行效果如果:

1. 編譯生成DLL

先新建項目,名稱為ocDLL:

應用程序設置見:

在解決方案資源管理器里可以看到已經有好個文件準備好了,把源文件里的文件類型全部由".cpp"改為".c",見下圖:

需要編輯的各文件的內容見下:

ocDLL.h

// ocDLL.h

#ifdef OCDLL_EXPORTS
#define OCDLL_API __declspec(dllexport)
#else

#define OCDLL_API __declspec(dllimport)
#endif

OCDLL_API int o_delimiter_replace(FILE * fpSrc, FILE * fpDst, const char chSrc, const char chDst);

stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include <windows.h>



// TODO: 在此处引用程序需要的其他头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

ocDLL.c

#include "stdafx.h"
#include "ocDLL.h"

OCDLL_API int o_delimiter_replace(FILE * fpSrc, FILE * fpDst, const char chSrc, const char chDst)
{
	long f_end;
	long f_now;
	long f_tmp;
	unsigned long i;
	unsigned long len_chAll;
	char * chAll;

	if( !(fpSrc && fpDst) )
			return -1;

	fseek( fpSrc, 0L, SEEK_END );
	f_end = ftell( fpSrc );
	fseek( fpSrc, 0L, SEEK_SET );

	chAll = (char*)calloc( f_end+3, sizeof(char) );
	if( !chAll )
		return -2;

	do{
		f_tmp = ftell( fpSrc );
		fgets( chAll, f_end+3, fpSrc );
		f_now = ftell( fpSrc );

		len_chAll = strlen(chAll);
		for( i = 0; i < len_chAll; i++ )
			if( chSrc == chAll[i] )
				chAll[i] = chDst;

		fputs( chAll, fpDst );
		chAll[0] = 0;
	}while(f_tmp < f_now );

	return 0;
}

在解決方案配置為Release下,生成解決方案。如果生成成功,將在輸出窗口中看到大概如下的信息:

1>------ 已启动生成: 项目: ocDLL, 配置: Release Win32 ------
1>  stdafx.c
1>  dllmain.c
1>  ocDLL.c
1>     正在创建库 d:\My Documents\Visual Studio 2010\Projects\ocDLL\Release\ocDLL.lib 和对象 d:\My Documents\Visual Studio 2010\Projects\ocDLL\Release\ocDLL.exp
1>  正在生成代码
1>  已完成代码的生成
1>  ocDLL.vcxproj -> d:\My Documents\Visual Studio 2010\Projects\ocDLL\Release\ocDLL.dll
========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
把生成的ocDLL.dll複製到Origin安裝目錄下的\OriginC\system\,再在該目錄里新建一個頭文件ocDLL.h:

#pragma dll(ocDLL,header)
int o_delimiter_replace(FILE * fpSrc, FILE * fpDst, char chSrc, char chDst);
把本文第一個程序代碼改為:

#include <origin.h>
#include <ocDLL.h>
int imp_one_line()
{
        string pstrOut;
        okutil_FileDialog(&pstrOut, FALSE);
       
        string pstrOut2;
        struct tm *nowtime;
        time_t aclock;
        time(&aclock);
        nowtime = localtime(&aclock);
        pstrOut2 = pstrOut + "-" + (nowtime->tm_year + 1900) + "-" + (nowtime->tm_mon + 1) + "-" + (nowtime->tm_mday);
        pstrOut2 = pstrOut2 + "-" + nowtime->tm_hour + "-" + nowtime->tm_min + "-" + nowtime->tm_sec + ".asc";
       
        FILE *fp1,*fp2;
        fp1 = fopen( pstrOut, "r" ) ;
        fp2 = fopen(pstrOut2, "w" ) ;
       
        fseek(fp1, 0L, SEEK_END ) ;
        int f_end = ftell(fp1);
        fseek(fp1, 0L, SEEK_SET ) ;
       
        char *chrAll = (char*)calloc(f_end+1,sizeof(char) ) ;
        if(!chrAll)
                return -1;
        fgets(chrAll,f_end,fp1 ) ;    // only ONE line of data
        MessageBox(GetWindow(), "Just for the first line of data. Please click OK to continue.","Warning!" ) ;
       
        Sleep(300 ) ;
        LT_execute("type -a Converting...." ) ;
        
        DWORD dw1 = GetTickCount();
        /*
        int lchrAll = lstrlen(chrAll ) ;
        for(int i=0;i<lchrAll;i++)
                if(44==(int)chrAll [ i ])
                        chrAll [ i ]=(char)10;
       
        fputs(chrAll,fp2 ) ;
        */
        o_delimiter_replace(fp1,fp2,',','\n');
        DWORD dw2 = GetTickCount();

       
        Sleep(300 ) ;
        LT_execute("type -a ....Done" ) ;
       
        printf("%d ms\n",dw2-dw1);
        
        fclose(fp1 ) ;
        fclose(fp2 ) ;
       
        Worksheet wks;
        wks.Create("origin" ) ;
        if(!wks)
                return -2;
        ASCIMP ai;
        if( 0 == AscImpReadFileStruct(pstrOut2, &ai) )
                if( 0 == wks.ImportASCII(pstrOut2, ai) )
                        out_str("Import data successful." ) ;
       
        return 0;
}
需要注意的是,上面的代碼在處理返回值方面有待改進。
編譯,執行,得:

2> imp_one_line()=
Converting....
....Done
188 ms
Import data successful.
imp_one_line()=0

儘管這樣子的比較不是很科學,但前後兩次所用時間差別很大,效率的提升相當明顯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值